Typescript — использование символов в качестве ключей объекта в файле объявления окружающего типа

#javascript #node.js #typescript

#javascript #node.js #машинописный текст

Вопрос:

У меня возникли проблемы с использованием символов с файлами объявления окружения TS в узле. Вот упрощенный пример того, что я хотел бы сделать:

 // lib/symbols.ts
export const coolSymbol = Symbol('cool');

// ambient.d.ts
declare const SymbolKey: unique symbol;
interface CoolObj {
  [SymbolKey]: string;
}

// app.ts
import * as symbols from './lib/symbols';
const obj: CoolObj = {
  [symbols.coolSymbol]: 'my key is a cool symbol',
};

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2017",
    "lib": [
      "ES2017"
    ],
    "module": "commonjs",
    "moduleResolution": "node",
    "noImplicitThis": true,
    "inlineSourceMap": true,
    "esModuleInterop": true,
    "noImplicitAny": true,
    "allowJs": true,
    "outDir": "dist"
  },
  "exclude": [
    "dist",
    "node_modules"
  ]
}

 

В этом примере я получаю ошибки проверки типов в app.ts:

 Element implicitly has an 'any' type because expression of type 'symbol' can't be used to index type 'CoolObj'.
 

TS не распознает, что мой тип CoolSymbol и тип фактического coolSymbol символа совпадают, поскольку все символы уникальны. Существует ли фундаментальная несовместимость между символами, значения которых определяются во время выполнения, и окружающими файлами TS, которые не передаются как JS?

Пара замечаний: использование модулей для типов вместо внешнего файла — не лучший вариант, поскольку для этого потребуется много рефакторинга существующего кода (а типов используется много). Это кодовая база, состоящая в первую очередь из JS, которую мы постепенно преобразуем в TS.

Что я пробовал:

  • Указание типа coolSymbol like so, что приводит к тому, что «Тип ‘typeof coolSymbol’ не может быть присвоен типу ‘typeof SymbolKey'».
 export const coolSymbol: typeof SymbolKey = Symbol('cool');
 
  • Указание типа coolSymbol использования as , т.е.
 export const coolSymbol = Symbol('cool') as typeof SymbolKey;
 

Я также был бы не против, если бы ключом был любой старый символ, а-ля [x: string]: string; нотация, но я слышал, что это будет доступно только до версии 4.2 (возможно).