繁体   English   中英

如何定义一个只接受可能是打字稿类型的参数的函数?

[英]How to define a function which only accepts parameters which may be a type in typescript?

我想定义一个函数,如:

function isNumber(param: ???): param is number {
}

如果参数可能是一个数字,例如number | string number | stringnumber | boolean number | boolean ,它可以传递给函数。 如果不是,例如它的类型是stringboolean ,就会出现编译错误。

是否可以定义这样的类型?

从概念上讲,您希望isNumber()param的类型T中通用,但您希望T下限number 这与被认为是上限的正常extends 约束相反。 不幸的是,TypeScript 不直接支持下界泛型。 这是在microsoft/TypeScript#14520中请求的,如果它曾经实现过,它可能会使用super而不是extends并且看起来像

// NOT VALID TS (as of 4.7), DON'T DO THIS
function isNumber<T super number>(param: T): param is number {
  return typeof param === "number"
}

但是,正如我所说,我们不能这样做。


相反,我们可以通过在条件类型上使用常规上限来模拟下界泛型。 T extends (U extends T ? unknown : never)这样的东西会表现得有点像T super U 如果TU的超类型,则(U extends T ? unknown : never)计算结果为unknown ,因此满足约束 ( T extends unknown )。 否则, (U extends T ? unknown : never)的计算结果为never ,因此可能不满足约束 ( T extends never )(除非T never自身,无法通过这种方式进行防范)。

在您的情况下,如果Tnumber的超类型或子类型,我们实际上很好,所以我们可以写T extends (number extends T ? unknown : number)并且如果T恰好是像14这样的数字文字类型,那么一切仍然作品。

一个问题是编译器不明白param可能是number的超类型,所以你不能返回类型谓词param is number 相反,您需要编写编译器认为可分配给T (和number )的类型。 所以我们将使用交集param is T & number

所以这里是:

function isNumber<T extends number extends T ? unknown : number>(
  param: T
): param is number & T {
  return typeof param === "number"
}

让我们测试一下:

isNumber("oops"); // error, Argument of type 'string' is 
// not assignable to parameter of type 'number'.
isNumber(Math.random() < 0.5 ? "abc" : 123); // okay
isNumber(14); // okay

看起来不错。

Playground 代码链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM