我正在检查不同的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
}
});
请注意,这也是一个更有效的迭代,尽管这在您的情况下可能无关紧要。
您的原始问题是filter
是T[] => 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!
}
游乐场