Я хотел бы настроить условное выражение, которое срабатывает, если переданный в него тип имеет индексную подпись. Пока вот что у меня есть:

type IsIndexed<T> = T extends {[key in string]: any} ?
    "type is indexed" :
    "type is not indexed";

const a: IsIndexed<boolean> = "type is not indexed";
const b: IsIndexed<{ [key: string]: number }> = "type is indexed";
const c: IsIndexed<{ prop: string }> = "type is not indexed"; // Type '"type is not indexed"' is not assignable to type '"type is indexed"'.

Как видно из комментария, имеется ошибка типа, поскольку TypeScript, похоже, рассматривает типы объектов без явной подписи индекса как подмножество тех, у которых она есть.

Это имеет смысл - если я пишу функцию и все, что ей нужно для запуска, это объект с ключами string и значениями boolean, нет причин, по которым объект, который соответствует этой форме с явно названными ключами, не может быть передан в нее, но для моих целей этого недостаточно.

Можно ли написать условный тип, который идентифицирует сигнатуры индекса иначе, чем явно названные ключи ?

0
Sandy Gifford 16 Апр 2020 в 00:49

1 ответ

Лучший ответ

Да, вы можете сделать это, проверив, является ли string подтипом keyof T для типа T. Если это так, то все строки являются действительными ключами; в противном случае ключи ограничены ограниченным набором имен ключей.

type Indexed = { [k: string]: number };
type NotIndexed = { x: number, y: number };

type Detect<T> = string extends keyof T ? 'Indexed' : 'Not Indexed';

type TestIndexed = Detect<Indexed>; // 'Indexed'
type TestNotIndexed = Detect<NotIndexed>; // 'Not Indexed'

Playground Link

2
kaya3 15 Апр 2020 в 22:01