Typescript允许为未定义的参数传递非未定义的值

时间:2018-03-02 20:13:46

标签: typescript

我在typescript playground中尝试了以下代码,并打开了所有选项。 我希望TS编译器只允许第一个call()有效。但是这四个都是。

通过将鼠标悬停在通话上,我看到它们输入为call<"String"|undefined>。 这里发生了什么?有没有办法强行检查?

interface IEndpoint<RequestType> { }
export const GetConsumer: IEndpoint<undefined> = {};
function call<RequestType>(rpc: IEndpoint<RequestType>, request: RequestType) {}

call(GetConsumer, undefined);
call(GetConsumer, null); // should not be allowed
call(GetConsumer, 1); // should not be allowed
call(GetConsumer, "String");  // should not be allowed

1 个答案:

答案 0 :(得分:4)

来自打字稿specification

  

未定义类型是所有类型的子类型。这意味着undefined被认为是所有基本类型,对象类型,联合类型,交集类型和类型参数的有效值。

让我们考虑打字稿如何解决以下情况:

class Base{ b: number}
class Derived extends Base{ c: number}
let GetDerived: IEndpoint<Derived>;
call(GetConsumer, new Base());

RequestType中的通用参数call有两种可能的类型:Derived(基于第一个参数)和Base(基于第二个参数)。 Typescript将为两者选择公共基本类型,因此RequestType将为Base

现在让我们考虑一下你的例子:

call(GetConsumer, 1);

与第一个示例类似,RequestType中的call可以是:undefined(基于第一个参数)和number(例如,基于第二个参数) 。由于undefined属于所有类型的子类型,因此它也是数字的子类型,因此最佳公共基类型为number

如果您正在寻找一种不允许最后两次通话的类型,void可以这样做,因为:

  

Void类型的唯一可能值是null和undefined。 Void类型是Any类型的子类型和Null和Undefined类型的超类型,但是Void与所有其他类型无关。

export const GetConsumer: IEndpoint<void> = {

};
call(GetConsumer, undefined);//still ok 
call(GetConsumer, null); // still ok 
call(GetConsumer, 1); // error
call(GetConsumer, "String");  // error