打字稿参数取决于另一个具有默认值的参数
Typesript argument depends on another argument with a default value
我正在尝试在打字稿中创建一个函数,其中第二个可选参数是第一个参数的键。没有可选参数,我想要的函数看起来像
function getVal<T>(obj: T, key: keyof T) {
return obj[key];
}
不过,我希望key
是可选的,取默认值"id"
。但是,函数
function getValBad<T>(obj: T, key: keyof T = "id") {
return obj[key];
}
不进行类型检查,因为打字稿不知道 T
是否具有 id
的键。这个问题的部分解决方法是写
function getValOk<T extends { id: any }>(obj: T, key: keyof T = "id") {
return obj[key];
}
但是,这会强制 T
始终具有 id
的键。
我的问题是,我能否编写一个函数 getValGood
,以便 getValGood({id: 1})
进行类型检查,getValGood({ID: 1}, "ID")
进行类型检查,而 getValGood({ID: 1})
不进行类型检查。如果是这样,我如何在打字稿中表示 getValGood
?
首先,您可能希望使用另一个通用参数来正确键入 returned 值。 (否则,obj[key]
将 return 对象上 所有 可能值的并集,而不是 just key
)
您可以重载 getVal
函数以获取对象和作为对象的 属性 的键(2 个泛型),或者仅使用单个泛型 { id: V }
和return 类型 V:
type GetVal = {
<T, K extends keyof T>(obj: T, key: K): T[K];
<V>(obj: { id: V }): V;
};
const getVal: GetVal = (obj: Record<string, unknown>, key = 'id') => {
return obj[key];
};
const result1 = getVal({ foo: 'foo' }, 'foo');
const result2 = getVal({ foo: 'foo' }, 'doesntexist'); // Fails
const result3 = getVal({ id: 'val' });
const result4 = getVal({ }); // Fails
我认为你应该为此使用函数重载:
function getVal<V>(obj: {id: V}): V;
function getVal<T, K extends keyof T>(obj: T, key: K): T[K];
function getVal(obj: any, key = 'id') {
return obj[key];
}
请注意,当函数具有重载签名时,Typescript 不会为您检查函数实现实际上是否分别符合每个重载签名;根据重载签名,确保您编写的实现是类型安全的取决于您。
Typescript 仍将至少确保对函数的每次调用都是正确键入的。
我正在尝试在打字稿中创建一个函数,其中第二个可选参数是第一个参数的键。没有可选参数,我想要的函数看起来像
function getVal<T>(obj: T, key: keyof T) {
return obj[key];
}
不过,我希望key
是可选的,取默认值"id"
。但是,函数
function getValBad<T>(obj: T, key: keyof T = "id") {
return obj[key];
}
不进行类型检查,因为打字稿不知道 T
是否具有 id
的键。这个问题的部分解决方法是写
function getValOk<T extends { id: any }>(obj: T, key: keyof T = "id") {
return obj[key];
}
但是,这会强制 T
始终具有 id
的键。
我的问题是,我能否编写一个函数 getValGood
,以便 getValGood({id: 1})
进行类型检查,getValGood({ID: 1}, "ID")
进行类型检查,而 getValGood({ID: 1})
不进行类型检查。如果是这样,我如何在打字稿中表示 getValGood
?
首先,您可能希望使用另一个通用参数来正确键入 returned 值。 (否则,obj[key]
将 return 对象上 所有 可能值的并集,而不是 just key
)
您可以重载 getVal
函数以获取对象和作为对象的 属性 的键(2 个泛型),或者仅使用单个泛型 { id: V }
和return 类型 V:
type GetVal = {
<T, K extends keyof T>(obj: T, key: K): T[K];
<V>(obj: { id: V }): V;
};
const getVal: GetVal = (obj: Record<string, unknown>, key = 'id') => {
return obj[key];
};
const result1 = getVal({ foo: 'foo' }, 'foo');
const result2 = getVal({ foo: 'foo' }, 'doesntexist'); // Fails
const result3 = getVal({ id: 'val' });
const result4 = getVal({ }); // Fails
我认为你应该为此使用函数重载:
function getVal<V>(obj: {id: V}): V;
function getVal<T, K extends keyof T>(obj: T, key: K): T[K];
function getVal(obj: any, key = 'id') {
return obj[key];
}
请注意,当函数具有重载签名时,Typescript 不会为您检查函数实现实际上是否分别符合每个重载签名;根据重载签名,确保您编写的实现是类型安全的取决于您。
Typescript 仍将至少确保对函数的每次调用都是正确键入的。