Сначала немного контекста к моему вопросу: у меня есть проект, в котором я получаю объект через Socket.IO, поэтому у меня нет информации о типе. Кроме того, это довольно сложный тип, поэтому необходимо много проверять, чтобы убедиться, что полученные данные хороши.
Проблема в том, что мне нужно получить доступ к свойствам локального объекта, заданного строками в полученном объекте. Это работает нормально для первого измерения, поскольку я могу привести спецификатор свойства типа any к keyof typeof
, к чему бы я ни хотел получить доступ (например, this.property[<keyof typeof this.property> data.property]
).
Тип результирующей переменной, очевидно, является довольно длинным типом объединения (объединяющим все типы всех свойств, которыми обладает this.property
). Как только одно из этих свойств не имеет примитивного типа, keyof typeof subproperty
определяется как never
.
Благодаря проверке, выполненной ранее, я могу гарантировать, что свойство существует, и я на 99% уверен, что код будет запущен после компиляции. Это просто компилятор, который жалуется.
Ниже приведен очень простой код, который воспроизводит это поведение вместе с наблюдаемыми и ожидаемыми типами.
const str = 'hi';
const obj = {};
const complexObj = {
name: 'complexObject',
innerObj: {
name: 'InnerObject',
},
};
let strUnion: typeof str | string; // type: string
let objUnion: typeof obj | string; // type: string | {}
let complexUnion: typeof complexObj | string; // type: string | { ... as expected ... }
let strTyped: keyof typeof str; // type: number | "toString" | "charAt" | ...
let objTyped: keyof typeof obj; // type: never (which makes sense as there are no keys)
let complexObjTyped: keyof typeof complexObj; // type: "name" | "innerObject"
let strUnionTyped: keyof typeof strUnion; // type: number | "toString" | ...
let objUnionTyped: keyof typeof objUnion; // type: never (expected: number | "toString" | ... (same as string))
let complexUnionTyped: keyof typeof complexUnion; // type: never (expected: "name" | "innerObject" | number | "toString" | ... and all the rest of the string properties ...)
let manuallyComplexUnionTyped: keyof string | { name: string, innerObj: { name: string }}; // type: number | "toString" | ... (works as expected)
Это известное ограничение TypeScript (версия 3) или я что-то здесь упускаю?