[英]How can I make a typesafe generic function
我认为这是可能的,但我在搜索正确的关键字时遇到了问题。 我有一个用于设置 object 的多个属性的方法,我希望它类型安全。
interface ICase {
caseDetails: ICaseDetails;
observations: IObservations;
}
interface ICaseDetails {
a: string;
}
interface IObservations {
b: number;
}
const updateCasePart = (state: ICase, payload: any, propName: keyof ICase) => {
state[propName] = payload
}
有没有一种方法可以输入有效负载,以便将调用 function 限制为正确的有效负载类型? 我知道我可以做payload: ICaseDetails | IObservations
payload: ICaseDetails | IObservations
但我希望得到类似payload: typeof keyof ICase
的东西
正如您的标题所暗示的那样,您应该按如下方式使 function通用:
const updateCasePart = <K extends keyof ICase>(
state: ICase, payload: ICase[K], propName: K
) => { state[propName] = payload }
我们没有将propName
参数注释为keyof ICase
类型(相当于联合类型"caseDetails" | "observations"
),而是将其注释为通用类型K
,该类型已被限制为keyof ICase
。 这允许propName
比keyof ICase
更具体。 例如,如果您将"caseDetails"
作为propName
传入,编译器将推断K
是字符串文字类型"caseDetails"
。
请注意, payload
的类型是索引访问类型ICase[K]
,这意味着ICase
在K
类型的键上的属性类型。 所以如果K
是"caseDetails"
,那么ICase[K]
就是ICaseDetails
。 这(主要)确保您为payload
传递的值是合适的。
赋值state[propName] = payload
type 检查是因为编译器将赋值的两边视为相同的通用类型ICase[K]
。
让我们测试一下:
declare const caseDetails: ICaseDetails;
declare const observations: IObservations;
declare const state: ICase;
updateCasePart(state, caseDetails, "caseDetails"); // okay
updateCasePart(state, caseDetails, "observations"); // error!
// -----------------> ~~~~~~~~~~~
// Argument of type 'ICaseDetails' is not assignable to parameter of type 'IObservations'.
updateCasePart(state, observations, "observations"); // okay
看起来不错。 编译器允许有效调用并且(大部分)不允许无效调用。
好吧,我一直说“大部分”。 有一个类型安全漏洞 generics 涉及工会; 如果出于某种奇怪的原因你传入了一个类型为键类型联合的propName
参数,那么K
将被推断为该联合,并且ICase[K]
也将是一个联合,这意味着可能允许错误调用:
updateCasePart(state, caseDetails,
Math.random() < 0.99 ? "observations" : "caseDetails"
); // okay?!
上面没有错误,但是有 99% 的可能性你已经将"observations"
作为propName
传递给ICaseDetails
作为payload
。
如果它真的很重要,可以开始重写updateCasePart
以减少此类事情发生的可能性......但是由于TypeScript 不是完全类型安全的,你不能真正阻止每一个可能的不安全操作,并且付出更多的努力会减少回报。
对于大多数用途,像上面这样的通用 function 提供了足够的安全性和可用性,因此我不会在这里进一步离题,详细说明在通往纯粹稳健性的无尽且越来越危险的无尽道路上可能发生的偏移。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.