打字稿重载箭头功能不起作用
Posted
技术标签:
【中文标题】打字稿重载箭头功能不起作用【英文标题】:Typescript overload arrow function is not working 【发布时间】:2019-09-30 06:03:59 【问题描述】:(我正在使用严格的空值检查)
我有以下箭头函数,具有重载类型:
type INumberConverter =
(value: number): number;
(value: null): null;
;
const decimalToPercent: INumberConverter = (value: number | null): number | null =>
if (!value)
return null;
return value * 100;
;
根据其他问题 (Can I use TypeScript overloads when using fat arrow syntax for class methods?) 的理解,这应该是有效的。永远不会出现以下错误:
TS2322: Type '(value: number | null) => number | null' is not assignable to type 'INumberConverter'. Type 'number | null' is not assignable to type 'number'. Type 'null' is not assignable to type 'number'
如果我定期编写这个函数(使用function
关键字):
function decimalToPercent(value: null): null;
function decimalToPercent(value: number): number;
function decimalToPercent(value: number | null): number | null
if (!value)
return null;
return value * 100;
它可以正常工作。
我需要使用箭头函数,所以 this
不会改变,我需要这个重载,所以 typescript 知道 decimalToPercent(1)
不能为空。
为什么它不能按照我的方式工作,我该如何解决?
【问题讨论】:
【参考方案1】:重载签名和实现签名之间的兼容性规则比赋值要宽松得多。
在这种情况下,您尝试将可能返回 null
的函数分配给具有禁止返回 null ((value: number): number;
) 的重载的函数。编译器会正确地发现这令人不安。对于重载,由于签名和实现都是作为一个单元编写的,编译器假定“你知道你在做什么”(正确与否)。
您可以通过多种方式解决它:
你可以使用类型断言,虽然你会失去大多数类型检查的实现,签名兼容性:
type INumberConverter =
(value: number): number;
(value: null): null;
;
const decimalToPercent = ((value: number | null): number | null =>
if (!value)
return null;
return value * 100;
) as INumberConverter;
您也可以像以前的ES5
一样使用常规的function
并捕获this
,尽管这种解决方案意味着复制大量的函数签名:
type INumberConverter =
(value: number): number;
(value: null): null;
;
class X
decimalToPercent: INumberConverter;
multiper = 100;
constructor()
let self = this;
function decimalToPercent(value: number): number;
function decimalToPercent(value: null): null;
function decimalToPercent(value: number | null): number | null
if (!value)
return null;
// use self
return value * self.multiper;
;
this.decimalToPercent = decimalToPercent;
或者可能最简单的解决方案是在构造函数中使用bind
并将函数编写为常规方法:
class X
decimalToPercent(value: number): number;
decimalToPercent(value: null): null;
decimalToPercent(value: number | null): number | null
if (!value)
return null;
return value * this.multiper;
;
multiper = 100;
constructor()
this.decimalToPercent = this.decimalToPercent.bind(this);
【讨论】:
“编译器会正确地发现这个问题”——你错了。这是你的假设。这应该是一个错误,应该修复。这是完全等价的。以上是关于打字稿重载箭头功能不起作用的主要内容,如果未能解决你的问题,请参考以下文章