索引类型的条件开关

Conditional Switch for Indexed Types

我想设置一个条件,如果传递给它的类型具有索引签名,它就会触发。到目前为止,这就是我所拥有的:

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 值的对象,那么没有理由适合该形状的对象无法将具有明确命名的键传递给它,但就我的目的而言,这还不够。

是否可以编写一个条件类型来标识索引签名,而不是明确命名的键

是的,您可以通过测试 string 是否是类型 Tkeyof 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