#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 (возможно).