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

问题描述 投票:2回答:1

我在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
typescript
1个回答
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(基于第二个参数)。打字稿将选择两者的共同基本类型,因此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
© www.soinside.com 2019 - 2024. All rights reserved.