1.首先
我曾经为理解子类型而苦苦挣扎,但我也为功能子类型而苦苦挣扎。
或者更确切地说,功能类型的亚型关系异常困难。
我写了一篇文章来表达我遇到的问题。
我们将分多个部分发布文章。
这一次,一个功能 按返回类型的子类型关系 是。
根据@uhyo 的“面向专业人士的 TypeScript 简介”进行学习。
如果您能指出我误解的地方,我将不胜感激。
2. 内容
1.首先
2. 内容
3.你可以从这篇文章中学到什么
4.环境
5. 功能亚型关系
5.1. 什么是子类型关系?
5.2. 什么是返回值类型的子类型关系?
5.3. void类型的子类型关系
六,结论
7. 参考
3.你可以从这篇文章中学到什么
您可以通过函数类型的返回类型来查看子类型关系。
如果 S (SubType) 是 T (SuperType) 的子类型,
对于相同的参数列表
一个函数类型 (引数リスト) => S (SubType)变成一个子类型 (引数リスト) => T (SuperType)
您将能够理解此源代码。
type Engineer = { name : string ; year : number ; }; type FrontendEngineer = { name : string ; year : number ; frontendSkill : Array < string > ; }; const hasFrontendSkill = ( frontendSkill : string []) => ({ name : ' daishi ' , year : 35 , frontendSkill , }); const hasEngineerSkill : ( frontendSkill : string []) => Engineer = hasFrontendSkill ; const daishiSkill : Engineer = hasEngineerSkill ([ ' JavaScript ' , ' TypeScript ' ]); console . log ( daishiSkill ); // { name: 'daishi', year: 35, frontendSkill: [ 'JavaScript', 'TypeScript' ] }
4.环境
打字稿:4.7.4 Node.js:16.15.15. 功能亚型关系
5.1 什么是子类型关系?
在我进入功能子类型之前,我想先讨论一下子类型。
什么是子类型关系?
当需要一种类型的值 A 并且可以用另一种类型的值 B 替换时, B 被称为 A 的子类型。
A 是超类型, B 是子类型。
SuperType 的一部分是 SubType。
(这与面向对象的继承关系相同。)
如果你把它应用到上一句,我想你可以更具体地看到它。
B (SubType) 是 A (SuperType) 的子类型,当您需要一种类型的值时, A (SuperType) 可以用另一种类型的值替换 B (SubType) 表示。
怎么样,是不是比较容易想象亚型关系? (只有我一个人吗?)
在这篇文章中,我能够通过表达 SuperType 和 SubType 来理解类型之间的关系,所以
甚至这也被描述为 SuperType 和 SubType。
之前发过一篇关于子类型关系的文章,请参考。
5.2. 什么是返回值类型的子类型关系?
现在,我们来看看主体的函数类型的返回值类型的子类型关系。
当您有以下情况时,
S (SubType) 是 T (SuperType) 的子类型 函数具有相同的参数列表函数类型的返回值成为子类型关系。
简而言之,
函数类型 (引数リスト) => S (SubType) 具有子类型关系 (引数リスト) => T (SuperType)。
在子类型关系的属性中
可以使用 S (SubType) 类型的值代替 T (SuperType) 类型的值。
通过将函数的返回类型的 S (SubType)类型值视为 T (SuperType)类型,
可以使用“返回 S (SubType)类型值的函数”代替“返回 T (SuperType)类型值的函数”。
比较混乱,还是看一下源码吧
// SuperType の定義 type Engineer = { name : string ; year : number ; }; // SubType の定義 type FrontendEngineer = { name : string ; year : number ; frontendSkill : Array < string > ; }; // SubType の関数 const hasFrontendSkill = ( frontendSkill : string []) => ({ name : ' daishi ' , year : 35 , frontendSkill , // ← frontendSkill: frontendSkill を省略 }); // SuperType の関数に SubType の関数を代入 const hasEngineerSkill : ( frontendSkill : string []) => Engineer = hasFrontendSkill ; // SuperType の関数を呼び出し 変数 daishiSkill に代入 const daishiSkill : Engineer = hasEngineerSkill ([ ' JavaScript ' , ' TypeScript ' ]); console . log ( daishiSkill ); // { name: 'daishi', year: 35, frontendSkill: [ 'JavaScript', 'TypeScript' ] }
FrontendEngineer (SubType) 类型是 Engineer (SuperType) 类型的子类型。
如果你不知道它是什么意思,请参考我之前发布的关于部分类型的文章。
具有相同参数列表的函数 (frontendSkill: string[])
hasFrontendSkill (SubType) 是 hasEngineerSkill (SuperType) 的子类型。
简而言之,
(frontendSkill: string[]) => FrontendEngineer (子类型)是
它是 (frontendSkill: string[]) => Engineer (SuperType) 的子类型。
现在让我们仔细看看。
函数 hasFrontendSkill 的类型为 (frontendSkill: string[]) => FrontendEngineer 。
const hasFrontendSkill = ( frontendSkill : string []) => ({ name : ' daishi ' , year : 35 , frontendSkill , // ← frontendSkill: frontendSkill を省略 });
这被分配给 (frontendSkill: string[]) => Engineer (SuperType)类型的函数 hasEngineerSkill 。
const hasEngineerSkill : ( frontendSkill : string []) => Engineer = hasFrontendSkill ;
它使用参数 ['JavaScript', 'TypeScript'] 调用函数 hasEngineerSkill ,并将其分配给变量 daishiSkill 。
函数 hasEngineerSkill 是 Engineer 类型,所以变量 daishiSkill 也是 Engineer 类型。
const daishiSkill : Engineer = hasEngineerSkill ([ ' JavaScript ' , ' TypeScript ' ]);
即使变量 daishiSkill 的类型是 Engineer (SuperType) 类型,也会返回 frontendSkill: [ 'JavaScript', 'TypeScript' ] 。
console . log ( daishiSkill ); // { name: 'daishi', year: 35, frontendSkill: [ 'JavaScript', 'TypeScript' ] }
“ Engineer 的类型定义中没有定义 frontendSkill 属性??”
你可能想知道,
这是,
hasEngineerSkill 是 Engineer 类型(SuperType)的函数, hasFrontendSkill 是不同于 FrontendEngineer 类型(SubType)类型的函数,
hasFrontendSkill (SuperType)赋值给 hasEngineerSkill (SubType),所以内容是同一个函数对象。
const hasEngineerSkill : ( frontendSkill : string []) => Engineer = hasFrontendSkill ;
所以调用任何一个都会给出相同的结果。
所以即使你用 hasEngineerSkill(['JavaScript', 'TypeScript']) 调用函数
变量 daishiSkill 包含一个具有 Engineer 和 FrontendEngineer 类型属性的对象。
像这种子类型关系,可以得到比变量中定义的类型信息 Engineer 更多的对象。
这是一个子类型关系容易混淆的概念......
我很困惑。
我觉得如果我能掌握SuperType和SubType哪个函数(个人印象)会更容易理解。
5.3. void类型的子类型关系
我希望你通过返回类型来理解子类型的关系,但是 void 类型有一个特殊的行为
返回任何类型的函数类型 (SubType) 被视为采用相同参数并返回类型 void 的函数类型 (SuperType) 的子类型。
让我们看看发生了什么。
由于 void 类型没有返回值,
可以使用任何返回任何值(SubType)的函数来代替不返回任何值的函数(SuperType)。
// SubType const f = ( name : string ) => ({ name }); // SuperType const g : ( name : string ) => void = f ;
函数 f 是 (name: string) => { name: string; } 类型的函数(SubType),
它可以分配给 (name: string) => void 类型函数 g (SuperType)。
我写的是特殊的,但是和前面通过返回值类型的子类型关系是一样的道理。
六,结论
这有点令人困惑......
一开始我完全不明白。
我花了几个小时才明白...
如果将 SuperType 和 SubType 应用于函数的返回值类型,可以看到子类型关系。
下次会更复杂 按参数类型的子类型关系 我会看看。
如果您也可以阅读其他文章,我会很高兴?♂️
7. 参考
书:面向有抱负的专业人士的 TypeScript 简介 Ryota Suzuki [作者]
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308626943.html
查看更多关于函数类型的子类型关系比较复杂,写SuperType和SubType可以理解(返回值类型的子类型关系)的详细内容...