假设我有一个函数,它访问对象中的值。
// TypeScript
function access<T, K extends keyof T>(object: T, key: K): T[K] {
return object[key];
}
const object: Record<string, any> = {
zero: 0,
one: 1,
two: "2",
};
const one = access(object, "one");
const two = access(object, "two");
字符串
有了这个,TypeScript可以计算出one
是一个数字,two
是一个字符串。到目前为止一切顺利。
但是现在,假设我想潜在地修改我在access
函数中获得的键。
// JavaScript
function identity(x) {
return x;
}
function access(object, key, modify = identity) {
return modify(object[key]);
}
const object = {
zero: 0,
one: 1,
two: "2",
};
const zero = access(object, "zero", Boolean);
const one = access(object, "one");
const two = access(object, "two", Number);
型
有没有一种方法可以告诉TypeScript zero
是一个布尔值,one
是一个数字,two
也是一个数字?比如,我可以告诉TypeScript我的access
函数将返回一个modify
参数返回的类型吗?
我试过这样的方法:
function identity(x: any): typeof x {
return x;
}
function access<T, K extends keyof T, V extends any>(object: T, key: K, modify: (x: V) => typeof x = identity): V {
return modify(object[key]);
}
型
虽然这正确地识别了zero
和two
,但one
仍然是未知的。
我也试过这个:
function access<T, K extends keyof T, V extends T[K]>(object: T, key: K, modify: (x: V) => typeof x = identity): V {
return modify(object[key]);
}
型
但这会将第三个参数标记为错误,因为它期望modify
函数返回与给定类型相同的类型。
有没有一种TypeScript的方法来做到这一点,或者我只是把事情复杂化了?
2条答案
按热度按时间4nkexdtk1#
如果我们不担心将
identity
用作default function argument,那么正确的类型如下所示:字符串
这里我们只是添加了一个新的类型
R
,对应于modify
的返回类型,其中modify
的输入类型是indexed access typeT[K]
。它的行为与预期的一样:型
当然,如果你需要的话,你需要传入
identity
。当尝试使用
identity
作为默认参数时,它会变得更加复杂。TypeScript中存在断开连接,这使得很难使用带有默认函数参数的generics。默认类型参数并不完全符合大多数人的期望。问题与 * 调用者 * 选择类型参数的事实有关,但是在这里,我们希望 * 实现 * 选择它,如果有人没有传入modify
属性。它就是不这样工作。在microsoft/TypeScript#56315有一个开放的功能请求,要求更好的东西。除非发生这种情况,否则最简单的解决方法是使用默认的泛型类型参数(当
modify
是indentity
时,那么上面的R
应该是T[K]
,所以我们默认为R = T[K]
),然后Assertidentity
是必要的类型(v: T[K]) => R
:型
这仍然是你想要的方式:
型
(The需要类型Assert的原因是没有什么能阻止疯狂的人显式地指定类型参数,
const crazy = access<type of object,“one”,string>(object,“one”); // const crazy:string
这是一件很奇怪的事情。但是编译器不能确定这不会发生。)
Playground链接到代码
vnzz0bqm2#
是的,在TypeScript中,您可以使用ReturnType实用程序类型定义函数的返回类型,键为引用其参数之一的属性。例如:
字符串
在此示例中,
getProperty
函数返回与其参数的指定属性的类型匹配的类型。