[TypeScript] 简述为什么要使用“普通函数类型”而不是“方法符号函数”?

1.首先

过去,我写过一篇关于函数子类型关系属性的文章。

在这篇文章中,方法符号放宽了子类型的属性,所以最好不要使用我总结了原因。

根据@uhyo 的“面向专业人士的 TypeScript 简介”进行学习。

如果您能指出我误解的地方,我将不胜感激。

2. 内容

1.首先

2. 内容

3.你可以从这篇文章中学到什么

4.环境

5. 为什么方法符号中的函数会放松子类型关系?

 5.1. 普通函数类型和方法符号的区别

 5.2. 为什么方法符号中的函数声明放宽了子类型关系

六,结论

7. 参考

3.你可以从这篇文章中学到什么

以方法表示法声明的函数是

不能使用以 SubType 作为参数的函数代替以 SuperType 作为参数的函数。

它放宽了子类型关系的特征。

我将使用下面的代码进行解释。

type Engineer = {
    name: string;
    year: number;
};

type FrontendEngineer = {
    name: string;
    year: number;
    frontendSkill: string;
};

type SelfIntroduction = {
    func: (engineer: Engineer) => string;
    method(engineer: Engineer): string;
}

const selfIntroductionEngineer: SelfIntroduction = {
    func: engineer => `名前は${engineer.name}です。実務経験は${engineer.year}です。`,
    method: engineer => `名前は${engineer.name}です。実務経験は${engineer.year}です。`,
};

const doSelfIntroduction = (frontendEngineer: FrontendEngineer) => `
    名前は${frontendEngineer.name}です。
    実務経験は${frontendEngineer.year}です。
    ${frontendEngineer.frontendSkill}ができます。
`;

// エラー: Type '(frontendEngineer: FrontendEngineer) => string' is not assignable to type '(engineer: Engineer) => string'.
selfIntroductionEngineer.func = doSelfIntroduction;

// これはエラーが発生しない
selfIntroductionEngineer.method =  doSelfIntroduction;

4.环境

  • 打字稿:4.7.4
  • Node.js:16.15.1

5. 方法符号中的函数放宽子类型关系

从这里开始,我们将看看“为什么方法符号中的函数声明会放松子类型关系?”

首先,我想简要回顾一下普通函数类型和方法符号中的函数声明。

5.1. 普通函数类型和方法符号的区别

方法符号是在对象字面量中创建函数的符号(即{ プロパティ: 式 })。

我以前写过这个,所以请看这里了解详细信息。

这一次,对象类型SelfIntroduction 定义了普通函数的类型和方法符号的函数。

type SelfIntroduction = {
    func: (engineer: Engineer) => string;
    method(engineer: Engineer): string;
}
  • func 用普通函数类型声明
  • method 在方法符号中声明

在对象类型中表示函数类型时,

  • 普通函数类型:関数名: (引数リスト) => 返り値の型
  • 方法符号:メソッド名(引数リスト): 返り値の型

变成。

既然您知道了普通函数和方法符号之间的区别,

让我们看一下主题,“方法符号中的函数声明是否放松了子类型关系?”

5.2. 为什么方法符号中的函数声明放宽了子类型关系

让我们看一下主题“为什么方法符号中的函数声明会放松子类型关系”。

正如我在开头所写的,我想使用以下源代码来看看它。

// SuperType のオブジェクトの定義 ...①
type Engineer = {
    name: string;
    year: number;
};

// SubType のオブジェクトの定義 ...②
type FrontendEngineer = {
    name: string;
    year: number;
    frontendSkill: string;
};

// 引数で SupetType の通常の関数とメソッド記法の関数をもったオブジェクトの型定義 ... ③
type SelfIntroduction = {
    func: (engineer: Engineer) => string;
    method(engineer: Engineer): string;
}

// ③ の型のオブジェクトを作成 ...④
const selfIntroductionEngineer: SelfIntroduction = {
    func: engineer => `名前は${engineer.name}です。実務経験は${engineer.year}です。`,
    method: engineer => `名前は${engineer.name}です。実務経験は${engineer.year}です。`,
};

// 引数で②の SubType を受け取る関数 ...㋐
const doSelfIntroduction = (frontendEngineer: FrontendEngineer) => `
    名前は${frontendEngineer.name}です。
    実務経験は${frontendEngineer.year}です。
    ${frontendEngineer.frontendSkill}ができます。
`;

// ④のオブジェクトの通常の関数型で宣言した関数に㋐の関数を代入 ... ㋑
// エラー: Type '(frontendEngineer: FrontendEngineer) => string' is not assignable to type '(engineer: Engineer) => string'.
selfIntroductionEngineer.func = doSelfIntroduction;

// ④のオブジェクトのメソッド記法で宣言した関数に㋐の関数を代入 ...㋒
// これはエラーが発生しない
selfIntroductionEngineer.method =  doSelfIntroduction;

这里有三个功能。

  • 功能doSelfIntroduction(㋐)

    (frontendEngineer: FrontendEngineer) => string 类型

  • 函数selfIntroductionEngineer.func(普通函数类型)(㋑)

    (engineer: Engineer) => string 类型

  • 函数selfIntroductionEngineer.method(方法符号函数)(㋒)

    (engineer: Engineer) => string 类型

安排好之后

  • ㋐是接收FrontendEngineer类型(②的子类型)作为参数并返回string类型的函数
  • ㋑㋒都是接收Engineer类型(①SuperType)作为参数并返回string类型的函数

这是

和,

函数doSelfIntroduction (㋐) 分配给函数selfIntroductionEngineer.func (㋑) 和函数selfIntroductionEngineer.method (㋒)。

// ④ オブジェクトの通常の関数型で宣言した関数に㋐の関数を代入 ... ㋑
selfIntroductionEngineer.func = doSelfIntroduction;

// ④ オブジェクトのメソッド記法で宣言した関数に㋐の関数を代入 ...㋒
selfIntroductionEngineer.method =  doSelfIntroduction;

然而,这些按参数类型的子类型关系被违反。

详细点,【TypeScript】根据函数类型的参数类型的子类型关系是不是太复杂了?所以,我把它写在文章中我试图分解它,以便即使是初学者也能理解它,

大致说来,

哦K

在论据中超类型接收作为参数的函数子类型可以代替接收 .

NG

在论据中子类型接收作为参数的函数超类型不能代替接收 .

这是子类型关系的属性。

这一次,是NG。子类型一个函数(㋐)接收超类型让我们处理它而不是接收 '.

所以你应该得到一个编译错误。

然后子类型让我们看一下每个分配了doSelfIntroduction (㋐) 的函数,其参数为 .

在普通函数类型中声明的函数selfIntroductionEngineer.func(㋑)是错误的。

// ④ オブジェクトの通常の関数型で宣言した関数に㋐の関数を代入 ... ㋑
// エラー: Type '(frontendEngineer: FrontendEngineer) => string' is not assignable to type '(engineer: Engineer) => string'.
selfIntroductionEngineer.func = doSelfIntroduction;

但是,在方法符号中声明的函数selfIntroductionEngineer.method (㋒) 是没有错误.

// ④ オブジェクトのメソッド記法で宣言した関数に㋐の関数を代入 ...㋒
// これはエラーが発生しない
selfIntroductionEngineer.method =  doSelfIntroduction;

这是,

“有论据子类型具有接收的功能超类型不能代替接收

它放宽了子类型关系的特征。

您正在破坏类型安全...

简而言之,

"以方法表示法声明的函数是子类型关系的属性宽慰是在做”

这就是它的意思。

六,结论

您可以看到为什么方法符号放宽了子类型关系的属性。

从现在开始,在对象字面量中声明函数时,

我想尝试在不使用方法表示法的情况下以普通函数类型声明它。

我终于明白了亚型关系,但还是很难……

如果您也可以阅读其他文章,我会很高兴?‍♂️

感谢您阅读到最后?

7. 参考

书:面向有抱负的专业人士的 TypeScript 简介 Ryota Suzuki [作者]

原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308628735.html