Leo*_*ang 5 javascript typescript
我有一个返回对象属性是否为 的函数undefined。我需要这个功能,而不是仅仅做,obj[key] === undefined因为否则有时我会得到Property 'foo' does not exist on type 'Bar'.. 当属性键是文字时,编写类型很简单。IE:
function hasDefinedProp<
Obj extends Partial<Record<string, any>>,
Prop extends string,
>(
obj: Obj,
prop: Prop,
): obj is Obj & Record<Prop, Prop extends keyof Obj ? Exclude<Obj[Prop], undefined> : unknown> {
return obj[prop] !== undefined;
}
const obj: Partial<Record<string, number>> = {};
if (hasDefinedProp(obj, 'foo')) {
obj.foo + 1; // No error.
obj.bar + 1; // "Object is possibly 'undefined'."
}
Run Code Online (Sandbox Code Playgroud)
但是,当键的类型是宽类型时,这不起作用,即:
const obj: Partial<Record<string, number>> = {};
const key: string = '';
if (hasDefinedProp(obj, key)) {
obj[key] + 1; // No error.
obj.bar + 1; // No error. Should be "Object is possibly 'undefined'."
}
Run Code Online (Sandbox Code Playgroud)
是否可以使类型保护适用于宽类型?
AFAIK,这是不可能的。一旦您添加了显式string类型const key: string = '';- TS 就无法缩小 的文字类型key。因此,您可以使用任何想要访问属性的字符串。本例中TS 无法用 type 来区分两种类型string:
const obj: Partial<Record<string, number>> = {};
const key: string = '';
if (hasDefinedProp(obj, key)) {
obj[key] + 1; // No error.
obj.bar + 1; // No error. Should be "Object is possibly 'undefined'."
}
Run Code Online (Sandbox Code Playgroud)
这让我想起了一个显式类型和不可变类型断言的例子:
const record: Record<string, number> = {
a: 1
} as const;
type Keys = keyof typeof record // string instead of "a"
Run Code Online (Sandbox Code Playgroud)
这意味着在这种特殊情况下,禁止使用宽类型可能是个好主意:
type ForbidWide<Prop> = Prop extends string ? string extends Prop ? never : Prop : never
function hasDefinedProp<
Obj extends Partial<Record<string, any>>,
Prop extends string,
>(
obj: Obj,
prop: ForbidWide<Prop>,
): obj is Obj & Record<Prop, Prop extends keyof Obj ? Exclude<Obj[Prop], undefined> : unknown> {
return obj[prop] !== undefined;
}
const obj: Partial<Record<string, number>> = {};
const key: string = '';
hasDefinedProp(obj, key) // error
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3380 次 |
| 最近记录: |