typescript:函数类型的协变和逆变

本文介绍了TypeScript中的函数类型兼容规则,区分了协变和逆变的概念,并详细讲解了TSConfig中的StrictFunctionTypes配置项,以及其对函数参数类型检查的影响。同时讨论了method和property声明在严格检查中的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、函数类型兼容规则

函数类型的参数类型使用子类型逆变(允许为其父类型)的方式确定是否成立,而返回值类型使用子类型协变(允许为其子类型)的方式确定

协变 :子类型可以赋值给父类型的情况

逆变:父类型可以赋值给子类型的情况

type AsFuncArgType<T> = (arg: T) => void;
type AsFuncReturnType<T> = (arg: unknown) => T;
//A≼B:表示A是B的子类
// 1 成立:(T -> Corgi) ≼ (T -> Dog)
type CheckReturnType = AsFuncReturnType<Corgi> extends AsFuncReturnType<Dog>
  ? 1
  : 2;

// 2 不成立:(Dog -> T) ≼ (Animal -> T)
type CheckArgType = AsFuncArgType<Dog> extends AsFuncArgType<Animal> ? 1 : 2;

 二、TSConfig 中的 StrictFunctionTypes

(1)StrictFunctionTypes配置项作用:

在比较两个函数类型是否兼容时,将对函数参数进行更严格的检查When enabled, this flag causes functions parameters to be checked more correctly),而实际上,这里的更严格指的即是 对函数参数类型启用逆变检查。

(2)在禁用了 strictFunctionTypes 的情况下,TypeScript 并不会抛出错误。这是因为,在默认情况下,对函数参数的检查采用 双变( bivariant  ,即逆变与协变都被认为是可接受的

 (3)在 TypeScript ESLint 中,有这么一条规则:method-signature-style,它的意图是约束在接口中声明方法时,需要使用 property 而非 method 形式:

// method 声明
interface T1 {
  func(arg: string): number;
}

// property 声明
interface T2 {
  func: (arg: string) => number;
}

1、进行如此约束的原因即,对于 property 声明,才能在开启严格函数类型检查的情况下享受到基于逆变的参数类型检查

2、对于 method 声明(以及构造函数声明),其无法享受到这一更严格的检查。因为在大部分情况下,我们确实希望方法参数类型的检查可以是双变的,这也是为什么它们的声明中类型结构使用 method 方式来声明:

interface Array<T> {
    push(...items: T[]): number;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值