索引类型的条件开关

San*_*ord 3 typescript conditional-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"'.
Run Code Online (Sandbox Code Playgroud)

正如您从注释中看到的,存在类型错误,因为 TypeScript 似乎将没有明确索引签名的对象类型视为具有明确索引签名的对象类型的子集。

这是有道理的 - 如果我编写一个函数,并且它需要运行的只是一个带有string键和boolean值的对象,那么没有理由不能将带有显式命名键的适合该形状的对象传递给它,但就我的目的而言,这不是'还不够。

是否可以编写一个条件类型来标识索引签名与显式命名的键不同

kay*_*ya3 7

是的,您可以通过测试 是否是该类型string的子类型来做到这一点。如果是,则所有字符串都是有效键;如果不是,则这些键被限制为一组有限的键名称。keyof TT

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'
Run Code Online (Sandbox Code Playgroud)

游乐场链接