【发布时间】:2021-11-28 10:51:32
【问题描述】:
我有一个泛型函数,它将返回一个泛型类型的对象或 null(可能未定义),所以我在返回类型中添加了 | null | undefined,但它似乎没有得到应用:
const test = <T>(obj: TypeA<T>): T | undefined | null => {
return someObject[obj];
};
当我查看生成的函数定义时,我得到const test: <T>(obj: TypeA<T>) => T(没有 null 或未定义)。这也意味着如果我这样称呼它:
test<number>(someNullArg).toPrecision()
TypeScript 不会抱怨,即使它应该抱怨,即使代码在运行时抛出 Cannot read properties of null 错误。如果我替换泛型类型,则返回类型正确生成 (const test: (obj: TypeA<any>) => any | undefined | null)。
更新
这是实际实现的简化版本:
let value;
const get = <T>(obj: Promise<T>): T | undefined | null => {
obj.then(val => value = val);
return value;
}
它接受一个 Promise 并返回它的值(如果它被解决了)。它被设计用于a StencilJS component 以在同步渲染方法中输出异步值。基本上我正在尝试重新创建Angular's async pipe 的功能。
第二次更新
我已尝试进一步调试,我认为这可能是 TypeScript 中的错误。
我把它简化为一个更简单的例子:
function test<T>(): T | undefined | null {
return (window as any).foo;
}
const x = test(); // type is "unknown"
const y = test<number>(); // type is "number"
y.toFixed(); // should throw a type error but doesn't
显然,一旦解析了泛型类型,| undefined | null 就会被完全忽略,我不知道为什么,因为返回类型非常具体。
Here's the entire source(重要的部分是async函数)。
【问题讨论】:
-
什么是
TypeA? -
TypeA
做什么? -
如果你不使用
--strictNullChecks,那么null和undefined会自动被吸收到任何联合中,它们本质上是never的同义词,参见@987654324 @。如果你想使用null和undefined作为有意义的类型,你真的应该使用--strictNullChecks。如果启用它会给您带来一堆错误,那么您应该单独清除它们(但这超出了所问问题的范围)。如果您可能接受,我很乐意将其写成答案。否则,请告诉我哪些问题仍未得到解答。 -
@fedonev 你是对的(我实际上对此感到惊讶,我认为已经解决的承诺会同步调用
then()回调,但事实并非如此)但就我而言,我实际上是强制一旦 Promise 解决,Stencil 组件将重新渲染,以便它获取已解决的值,因此它再次调用该函数。如果你有兴趣这里的代码:gist.github.com/tricki/e897f3e40c15fd4dfa089a0c942acf18 -
任何关心
null和undefined的人都应该启用--strictNullChecks,因为这就是该功能的重点。我真的不知道如果您将其关闭会发生什么,但包含您的代码的人会打开它,反之亦然。我的建议是始终打开它......通常是整个--strictsuite of compiler features 以获得“标准”数量的类型安全。然后null和undefined将完全按照您的预期进行。不过,我仍在等待 github 完全活跃以找到相关问题。
标签: typescript typescript-generics