索引类型参数的打字稿默认值

时间:2020-07-07 09:12:44

标签: typescript typescript-typings type-constraints

请考虑Typescript文档中Index types section的以下代码段:

function getProperty<T, K extends keyof T>(o: T, propertyName: K): T[K] {
    return o[propertyName]; // o[propertyName] is of type T[K]
}

此函数返回o的属性之一,并且相当精细的类型签名可确保类型检查器在编译时评估此属性是否确实存在,这非常简洁。

对于另一个不同但相似的函数,我想使用propertyName作为默认值,因此不必显式传递它,即

function getProperty<T, K extends keyof T>(o: T, propertyName: K = "default"): T[K]

不过,编译器不喜欢这样,并且在函数定义时引发以下错误:

Type '"default"' is not assignable to type 'K'.
'"default"' is assignable to the constraint of type 'K', but 'K' could be instantiated with a different subtype of constraint 'string | number | symbol'.

我知道数字和符号(?)也可以是有效的索引,但这不是为什么我不能将字符串指定为propertyName的默认值。有人可以解释为什么这是一个问题,是否有可能解决它?

1 个答案:

答案 0 :(得分:2)

这里有两个可能的问题:

  1. T可能没有"default"属性
  2. 可以通过显式提供通用类型参数来调用
  3. getProperty
    例如getProperty<Foo, "someProp">(...),因此"default"无法分配给该类型

一种可能的解决方案是定义overloads:一种不带属性名(使用默认值),另一种允许提供属性名:

function getProperty<T extends { "default"?: any }>(o: T): T["default"]
function getProperty<T, K extends keyof T>(o: T, propertyName: K): T[K]
function getProperty(o: any, propertyName = "default") {
    return o[propertyName];
}

Playground