传递给函数时对象中键的打字稿缩小 [英] Typescript narrowing of keys in objects when passed to function
问题描述
为什么 TypeScript 不对对象的成员应用类型缩小到对象类型本身,以便它可以传递给另一个需要缩小类型的函数?如何在不失去类型安全性的情况下修复/规避此问题?
Why does TypeScript not apply type narrowing on members of objects to the object type itself, such that it can be passed to another function that expects a narrowed type? How can this be fixed/circumvented without loosing typesafety?
最小示例:
type A = { key: string | null};
type B = {key: string};
function func(a: B) {};
const a: A = {key:'abcd'};
if(typeof(a.key)==='string') {
a.key // has (narrowed) type 'string'
func(a); // still does not work
}
错误消息是:属性key"的类型不兼容.输入'字符串|null' 不能分配给类型 'string'.
推荐答案
这最终是一个 TypeScript 的设计限制.它不在对象的属性上使用类型保护来缩小对象本身,除非在对象是 discriminated union 类型的特殊情况... 就您而言, A
根本不是联合,更不用说是受歧视的联合了.
This is ultimately a design limitation of TypeScript. It does not use type guards on an object's properties to narrow the object itself, except in the particular case where the object is a discriminated union type... and in your case, A
isn't a union at all, let alone a discriminated one.
我为您的案例执行此操作的方法是引入 用户定义的类型保护函数,它明确地执行您期望的缩小:您传入一个具有 key
属性的对象,并返回 true
或 false
取决于此对象是否是有效的 B
:
The way I'd do this for your case is to introduce a user-defined type guard function which explicitly performs the narrowing you expect: you pass in an object with a key
property, and return true
or false
depending on whether or not this object is a valid B
:
const isB = (x: { key: any }): x is B => typeof x.key === "string";
然后你使用它:
if (isB(a)) {
func(a); // okay
}
这(给予或接受函数调用)与您的代码基本相同的逻辑,但编译器现在可以识别您的意图.好的,希望有帮助;祝你好运!
This is (give or take a function call) essentially the same logic as your code, but the compiler recognizes your intent now. Okay, hope that helps; good luck!
这篇关于传递给函数时对象中键的打字稿缩小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!