use*_*501 5 javascript typescript ecmascript-6
当一个对象有一个可能未定义的 id 且您想要从这些对象的数组中选择所有现有 id 时,为什么以下代码会产生 Typescript 错误,指出 y.id 可能未定义?
.filter(x => x.id !== undefined).map(y => y.id)
Run Code Online (Sandbox Code Playgroud)
问题是它.filter()不会自动更改数组的类型。如果有Array<T>则再次.filter()生产Array<T>。毕竟,确定要过滤的内容并不容易。考虑一下:
const input = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ name: "Carol" },
{ name: "David" },
];
const result = input.filter(x => x.name.includes("o"));
console.log(result);Run Code Online (Sandbox Code Playgroud)
Array<{id?: number, name: string}>将类型从更改为 是否正确Array<{id: number, name: string}>?不,不会的。过滤器显然仍然会产生可能没有id属性的项目。如果您不了解数据,那么就更难确定过滤的作用及其用途。
然而,TypeScript确实有打字功能
interface Array<T> {
filter<U extends T>(pred: (a: T) => a is U): U[];
}
Run Code Online (Sandbox Code Playgroud)
或者.filter()从 转换为 的Array<T>方法Array<U>。它接受一个类型保护,该保护应该告诉它过滤产生一个新类型。因此,您可以做的是使用类型保护,让 TypeScript 编译器相信在执行以下操作后,您拥有了 ID。请注意,类型保护必须返回布尔值:
interface Array<T> {
filter<U extends T>(pred: (a: T) => a is U): U[];
}
Run Code Online (Sandbox Code Playgroud)
id但是,这不会捕获该属性可能存在的情况,但null例如undefined:
interface MyType {
id?: number;
name: string;
}
input
.filter((x): x is MyType & {id: number} => "id" in x)
.map(y => y.id);
Run Code Online (Sandbox Code Playgroud)
所以,你需要修改逻辑(x): x is MyType & {id: number} => "id" in x && typeof x.id === "number"。这开始变得笨拙,并且如果您有不同的类型(例如
interface MyType {
id?: number | null | undefined;
name: string;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用泛型来概括类型保护,因此它将检查可能具有以下内容的任何类型id:
interface Foo {
id?: number | null | undefined;
bar: string
}
Run Code Online (Sandbox Code Playgroud)
这将允许您轻松过滤包含类型的数组id:
type IdType<T extends {id?: any}> = T["id"]; //what is the type of the `id` property
type HasId<T> = T & {id: Exclude<IdType<T>, null | undefined>}; // T with a mandatory and non-null `id` property
function hasId<T extends { id?: any }>(item: T): item is HasId<T>{
return "id" in item // has `id`
&& item.id !== undefined // isn't `undefined`
&& item.id !== null; // isn't `null`
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2664 次 |
| 最近记录: |