为什么 TypeScript 无法推断类型,并且在筛选该属性后仍将此属性视为 null?

  • 本文关键字:属性 筛选 null TypeScript 类型 typescript
  • 更新时间 :
  • 英文 :


我正在检查不同的TypeScript版本。TypeScript有多聪明让我很惊讶,但是这个…?

type Product = { id: number, imageUrl: null | string };
const products: Product[] = [
{ id: 1, imageUrl: 'assets/img/1.jpg' },
{ id: 2, imageUrl: null }
];
products.filter(p => null !== p.imageUrl).forEach(p => {
p.imageUrl; // null | string
});

是我做错了什么还是只是语言的限制?

这是当前语言的一个限制。然而,如果你想遵循它们,GitHub中有一些开放的问题:#38390,#16069您可以添加类型保护,它应该工作(如参考问题中的建议):

type Product = { id: number, imageUrl: null | string };
const products: Product[] = [
{ id: 1, imageUrl: 'assets/img/1.jpg' },
{ id: 2, imageUrl: null }
];
products.filter((p): p is {id: number, imageUrl: string } => null !== p.imageUrl).forEach(p => {
p.imageUrl; // string
});

这是语言的限制,但一个简单的通用解决方案是使用is语法向下游传递此信息

products
.map(
(p: Product) => p.imageUrl
)
.filter(
(imageUrl: string | null): imageUrl is string => !!imageUrl
)
.forEach(
(imageUrl: string) => {
imageUrl; // string
}
);

打印稿操场

这是你必须使用语言的时候之一:

type Product = { id: number, imageUrl: null | string };
const products: Product[] = [
{ id: 1, imageUrl: 'assets/img/1.jpg' },
{ id: 2, imageUrl: null }
];
products.forEach(p => {
if (p.imageUrl) {
// here the typechecker knows it's not null
}
});

请注意,这也是一个更有效的迭代,尽管这在您的情况下可能无关紧要。

您的原始问题是filterT[] => T[]的函数,而不是T[] => SomeSubsetOfTTheCompilerKnowsYouNullChecked[]的函数。

编译器可以在给定的作用域/块中判断访问是否被检查,如果有错误路径,甚至可以这样做(在最近的版本中):

function f(x: null | string) {
if (x === null) {
throw new Error('oops');
}
x.repeat(3); // safe!
}

…但是它不能在函数调用之间这样做:

function g(x: null | string) {
return x;
}
const maybeString = Math.round(Math.random()) ? 'hi' : null;
if (maybeString) {
const a = g(maybeString); // type is still null | string!
}

游乐场

最新更新