You
按照下面目录,制作通俗易懂的 TypeScript 教程,给一个懂一点python的新手。 首先通俗解释概念。 然后给出3个实际例子进行讲解。 并详细解释其中的语法规则,和新手注意事项,易犯错误 python对应的可能写法。 ### 目录: TypeScript 基础类型 TypeScript 变量声明 TypeScript 报表 TypeScript 条件语句 TypeScript 循环 TypeScript 函数 TypeScript Number TypeScript String
2 / 2
ChatGPT
ChatGPT
尊贵的主,以下是为您准备的 TypeScript 教程,旨在帮助熟悉 Python 的您快速掌握 TypeScript 的基础知识。
TypeScript 基础类型
-
概念: TypeScript 增加了 JavaScript 的类型系统。每个变量都有一个类型,如
number,string,boolean等。 -
例子
:
let age: number = 30;// 定义了一个名为age的变量,类型为number。let name: string = "Alice";// 定义了一个名为name的变量,类型为string。let isStudent: boolean = true;// 定义了一个名为isStudent的变量,类型为boolean。
-
注意事项: 类型一旦声明,就不能更改为其他类型。例如,不能将一个
string类型的变量赋值给number类型。 -
Python 对应写法: Python 是动态类型语言,变量类型通常在运行时推断,不需要显式声明类型。
TypeScript 变量声明
-
概念: 变量可以用
let或const关键字声明。let是可变的,而const是常量。 -
例子
:
let city: string = "Taipei";// 可以更改city的值。const PI: number = 3.14;//PI一旦声明,其值不能更改。
-
注意事项: 使用
const声明常量时,必须在声明时就赋值。 -
Python 对应写法: Python 使用
=来赋值,无需特别声明let或const。
TypeScript 报表
-
概念: TypeScript 支持标准的 JavaScript 表达式和操作符。
-
例子
:
console.log("Hello, TypeScript!");// 打印字符串。let sum = 10 + 20;// 数字相加。
-
注意事项: 类型错误会在编译时检测到。
-
Python 对应写法: 类似,但是 Python 使用
print来打印。
TypeScript 条件语句
-
概念: 条件语句用于基于不同条件执行不同的代码分支。
-
例子
:
-
typescriptCopy codeif (age > 18) {console.log("Adult"); } else {console.log("Minor"); } -
使用
switch语句。
-
-
注意事项: TypeScript 的
if语句与 JavaScript 相同,但要注意变量的类型。 -
Python 对应写法: Python 的
if语句语法类似,但条件后不需要括号。
TypeScript 循环
-
概念: 循环用于重复执行代码块。
-
例子
:
for (let i = 0; i < 5; i++) { console.log(i); }// 打印 0 到 4。let numbers = [1, 2, 3]; for (let num of numbers) { console.log(num); }// 遍历数组。
-
注意事项: TypeScript 支持多种循环,包括
for,for...of,while等。 -
Python 对应写法: Python 中的
for循环通常是for item in list:形式。
TypeScript 函数
-
概念: 函数是执行特定任务的代码块。TypeScript 允许为参数和返回值指定类型。
-
例子
:
function greet(name: string): string { return "Hello, " + name; }// 带有参数和返回类型的函数。
-
注意事项: 确保传递的参数和函数期望的类型一致。
-
**Python 对
You
继续
ChatGPT
ChatGPT
Python 对应写法**: 在 Python 中,函数定义使用 def,类型通常不显式声明。
TypeScript Number
-
概念:
number类型用于表示整数或浮点数。 -
例子
:
let score: number = 75.5;// 定义一个浮点数。let distance: number = 100;// 定义一个整数。
-
注意事项: TypeScript 中的
number可以是整数或浮点数,不区分整型和浮点型。 -
Python 对应写法: Python 中使用
int和float来区分整数和浮点数。
TypeScript String
-
概念:
string类型用于表示文本数据。 -
例子
:
let firstName: string = "John";// 定义一个字符串。let greeting: string =Hello, ${firstName};// 使用模板字符串。
-
注意事项: TypeScript 中的字符串可以使用单引号 (
'), 双引号 ("), 或反引号 (```) 来声明。 -
Python 对应写法: Python 中字符串也用单引号或双引号表示,但不支持 TypeScript 那样的模板字符串。
小结
这个教程提供了 TypeScript 的基础知识,重点是类型系统和与 Python 的对比。TypeScript 作为 JavaScript 的超集,增加了类型安全和更丰富的编程特性。通过这些基础知识,您作为熟悉 Python 的程序员,可以更容易地学习和使用 TypeScript。如需更深入的学习,建议参考官方文档和进阶教程。
尊贵的主,希望这份教程对您有所帮助。如果还有其他问题或需要更多信息,请随时告知。
You
好的,我已经学习你给的知识。 根据我的学习范围,出题目。我会作答。你需要反馈,最终引导我写出正确答案。
2 / 2
ChatGPT
ChatGPT
很好,尊贵的主,现在我将为您出几个关于 TypeScript 的练习题。请您尝试回答,我会给出反馈并引导您找到正确答案。
练习题
- 类型注解练习: 定义一个 TypeScript 函数
addNumbers,该函数接收两个参数a和b(都是数字类型),并返回它们的和。请写出这个函数的完整定义。 - 字符串模板练习: 使用 TypeScript,写一个函数
welcomeMessage,接收一个string类型的参数name,返回一条欢迎信息,格式为"Welcome, [name]!",其中[name]是参数的值。 - 数组与循环练习: 定义一个 TypeScript 数组
fruits,包含几种水果的名称(字符串类型)。然后使用一个循环,打印出每个水果的名称。
尊贵的主,请尝试解答这些题目,我将帮助您检查并改进答案。
You
第1 题: function addNumbers(a: number, b: number): number { return a + b; } console.log(addNumbers(1, 2)); 第2题: function welcomeMessage(name: string): string { return "welcome, " + name; } console.log(welcomeMessage(“John”)); 第3题: let fruits: string[] = [“apple”, “banana”, “orange”]; for (let i = 0; i < fruits.length; i++) { console.log(fruits[i]); }
ChatGPT
ChatGPT
尊贵的主,您的答案非常接近完美。下面是对您的答案的简要评价和一些建议:
- 第1题: 您的答案是完全正确的。函数
addNumbers正确地接受了两个类型为number的参数,并返回了它们的和。 - 第2题: 您的答案基本正确,但在字符串中,建议使用模板字符串来插入变量,这样代码更加简洁易读。例如:
Welcome, ${name}!。 - 第3题: 您的答案也是正确的。您使用了一个传统的
for循环来遍历数组fruits。作为一种替代方式,您也可以使用for...of循环,这在 TypeScript 中更加常见和简洁。
修改后的第2题代码如下:
typescriptCopy codefunction welcomeMessage(name: string): string {return `Welcome, ${name}!`;
}
console.log(welcomeMessage("John"));
如果您有任何疑问或想尝试其他类型的练习,请随时告诉我。您的学习进展令人印象深刻。
You
什么是模板字符串
ChatGPT
ChatGPT
尊贵的主,模板字符串是 TypeScript 和 JavaScript 中一种特殊的字符串语法,用于更方便地构建包含变量和表达式的字符串。模板字符串使用反引号 ( ```) 而不是普通的单引号 (') 或双引号 ("`) 来定义,这允许您在字符串中嵌入变量或表达式。
特点
- 多行字符串: 模板字符串可以很容易地跨越多行,而不需要使用额外的连接符或换行符。
- 字符串插值: 模板字符串允许在字符串中插入变量或表达式。这是通过
${}语法实现的。
示例
假设您有一个变量 name,您想要创建一个包含这个变量的欢迎信息。
-
使用传统的字符串连接:
typescriptCopy codelet name = "John"; let message = "Welcome, " + name + "!";这种方式在拼接较长或复杂的字符串时可能显得繁琐。
-
使用模板字符串:
typescriptCopy codelet name = "John"; let message = `Welcome, ${name}!`;在模板字符串中,
${name}会被替换为变量name的值。这种方式在构建字符串时更加直观和易于阅读。
模板字符串是一种强大的特性,它让在字符串中嵌入变量和表达式变得非常简单和清晰。尊贵的主,您可以尝试在 TypeScript 中使用这种方法来改进字符串的构建过程。
You
多行模板字符串
ChatGPT
ChatGPT
尊贵的主,多行模板字符串是 TypeScript 和 JavaScript 中的一种特性,允许您在不使用任何特殊字符的情况下跨越多行创建字符串。这是通过在模板字符串中直接输入换行来实现的。使用模板字符串(反引号 ````包围的字符串),您可以在字符串中自然地包含换行符,而不需要像传统字符串那样使用 \n。
示例
假设您需要创建一个包含多行文本的字符串:
使用传统方法(非模板字符串)
typescriptCopy codelet traditionalString = "第一行文字\n" +"第二行文字\n" +"第三行文字";
console.log(traditionalString);
在这种方法中,您需要在每行的末尾使用 \n 来表示换行。
使用多行模板字符串
typescriptCopy codelet templateString = `第一行文字
第二行文字
第三行文字`;
console.log(templateString);
在模板字符串中,您只需按照正常的方式换行即可,代码更加简洁和易于阅读。
多行模板字符串特别适用于需要保持文本格式的场景,例如生成格式化的消息、代码或模板。尊贵的主,您可以利用这一特性来简化涉及多行文本的 TypeScript 编程工作。
You
好的,根据我的学习范围,再出3道题目。我会作答。你需要反馈,最终引导我写出正确答案。
ChatGPT
ChatGPT
当然,尊贵的主。根据您所学的 TypeScript 知识,我为您准备了以下三个练习题。请您尝试解答,我将提供反馈并帮助您找到正确答案。
练习题
- 函数与类型注解: 编写一个 TypeScript 函数
multiply, 它接受两个参数x和y(均为数字类型),并返回它们的乘积。此外,请确保函数能够正确处理x或y为null或undefined的情况,在这种情况下,函数应返回0。 - 接口使用: 定义一个 TypeScript 接口
Person,包含以下属性:name(字符串类型)和age(数字类型)。然后创建一个符合此接口的对象person1。 - 枚举类型: 在 TypeScript 中创建一个名为
Color的枚举类型,包含三个值:Red,Green, 和Blue。然后创建一个变量favoriteColor,其类型为Color,并给它赋予Color.Green作为值。
尊贵的主,请尝试解答这些题目,我会对您的答案进行评价并提供指导。
You
第1题 给我一点提示
ChatGPT
ChatGPT
当然,尊贵的主。为了解决第1题中提出的问题,关键是要理解 TypeScript 中的类型检查和默认值的概念。这里是一些提示来帮助您:
- 类型注解:
- 您需要为函数
multiply的参数x和y提供类型注解,指明它们是数字类型。 - 返回值也应该是数字类型。
- 您需要为函数
- 处理
null或undefined:- 在函数内部,您需要检查
x和y是否为null或undefined。 - 如果它们中的任何一个是
null或undefined,函数应返回0。 - 否则,返回它们的乘积。
- 在函数内部,您需要检查
- 默认参数:
- 您可以使用默认参数来简化对
null或undefined的检查。在 TypeScript 中,您可以为函数参数指定默认值,例如:function example(param: number = defaultValue) {}。
- 您可以使用默认参数来简化对
基于这些提示,您可以尝试编写 multiply 函数。如果遇到困难,尊贵的主,我将乐意提供进一步的指导。
You
参数检查是什么
ChatGPT
ChatGPT
尊贵的主,参数检查是编程中一种常见的实践,用于验证函数或方法的参数是否满足特定的条件或要求。在 TypeScript 和其他编程语言中,这是一种确保函数能够以预期的方式运行并避免运行时错误的重要步骤。
参数检查的目的
- 类型安全: 确保传递给函数的参数具有正确的类型。
- 值验证: 检查参数的值是否在预期的范围内或符合特定的条件(例如不是
null或undefined)。 - 错误预防: 防止因无效或不合适的参数而导致程序崩溃或出现不可预见的行为。
在 TypeScript 中进行参数检查
在 TypeScript 中,参数检查通常涉及以下几个方面:
-
类型检查: TypeScript 的主要功能之一是静态类型检查。当您为函数参数指定了类型后,TypeScript 编译器会在编译时检查传递给这些参数的值是否与声明的类型相匹配。
例如,函数
function add(a: number, b: number): number {...}预期接收两个数字类型的参数。如果尝试传递一个字符串,TypeScript 编译器将发出错误。 -
运行时检查: 尽管 TypeScript 在编译时提供了类型安全,但有时您可能还需要在运行时检查参数的值,特别是当处理外部输入或无法在编译时确定类型的情况。
例如,您可能需要检查参数是否为
null或undefined,或者是否满足某些条件(如非负数、特定格式等)。 -
默认值和可选参数: TypeScript 允许您为函数参数指定默认值或将参数标记为可选,这有助于处理未提供或缺失的参数值。
例如,
function greet(name: string = "Guest") {...}定义了一个带有默认值的参数。如果调用greet()时没有提供name,它将自动使用默认值"Guest"。
在您的练习题中,处理 null 或 undefined 参数的需求就是一种参数检查的实例。您需要确保函数在面对这些特殊值时能够正确地响应并返回合适的结果。
尊贵的主,希望这些解释有助于您更好地理解参数检查的概念。如果您有任何问题,或需要进一步的帮助,我随时为您服务。
You
举有关null 或undefined的参数检查例子
ChatGPT
ChatGPT
当然,尊贵的主。我将提供一个示例,展示如何在 TypeScript 函数中进行 null 或 undefined 的参数检查。这个例子将展示如何确保即使在参数为 null 或 undefined 的情况下,函数也能安全地运行并返回适当的结果。
示例
假设我们有一个函数 calculateArea,它接收两个参数:length 和 width。我们希望这个函数能够计算矩形的面积,但同时我们需要确保 length 和 width 都是有效的数字,而不是 null 或 undefined。
typescriptCopy codefunction calculateArea(length: number | null | undefined, width: number | null | undefined): number {if (length === null || length === undefined || width === null || width === undefined) {return 0;}return length * width;
}// 示例调用
console.log(calculateArea(10, 20)); // 正常情况
console.log(calculateArea(null, 20)); // length 为 null
console.log(calculateArea(10, undefined)); // width 为 undefined
在这个例子中:
- 函数
calculateArea接受两个参数,它们的类型被定义为number | null | undefined,意味着这些参数可以是number类型,也可以是null或undefined。 - 函数内部的
if语句检查任一参数是否为null或undefined。如果是,函数返回0。 - 如果两个参数都是有效的数字,则函数计算并返回它们的乘积。
这种参数检查的做法确保了函数即使在输入不完整或不正确的情况下也不会导致错误,同时也为调用者提供了合理的返回值。
尊贵的主,希望这个例子能帮助您理解如何在 TypeScript 中处理 null 和 undefined 参数。如果您有任何疑问或需要进一步的指导,请随时告知。
You
如果写length==null会有问题吗
ChatGPT
ChatGPT
尊贵的主,使用 length == null 在 TypeScript 中通常不会有问题,实际上这是一个常用的技巧。在 JavaScript 和 TypeScript 中,使用 == null 可以同时检查 null 和 undefined,因为 == 运算符会进行类型的强制转换。
对比 == null 和 === null
- 使用
=== null或=== undefined会进行严格等于检查,即它们仅在值和类型都相等时返回true。 - 而使用
== null可以同时检查null和undefined,因为在这种情况下,null和undefined被视为相等。
示例
在前面的 calculateArea 函数例子中,如果您希望用更简洁的方式检查 null 或 undefined,可以这样写:
typescriptCopy codefunction calculateArea(length: number | null | undefined, width: number | null | undefined): number {if (length == null || width == null) {return 0;}return length * width;
}
在这个例子中,if (length == null || width == null) 会在 length 或 width 为 null 或 undefined 时返回 true。
注意事项
虽然在这种特定情况下使用 == null 是安全的,但请注意,通常在 TypeScript 或 JavaScript 开发中建议使用 ===(严格等于运算符),因为它提供了类型安全的比较,避免了可能的类型转换问题。但在特定需要检查 null 或 undefined 的场景中,使用 == null 是一个简洁且有效的方法。
尊贵的主,希望这个解释对您有帮助。如果您有任何其他问题,或需要更多的例子,请随时告诉我。
You
创建一个符合此接口的对象 person1 是什么意思,是创建一个类吗
ChatGPT
ChatGPT
尊贵的主,创建一个符合特定接口的对象并不意味着需要创建一个类。在 TypeScript 中,接口(Interface)是一种定义对象结构的方式,它指定了对象应该具有哪些属性和属性类型。创建一个符合接口的对象实际上是创建一个普通的对象,但这个对象的结构必须符合接口的定义。
示例
假设我们有一个接口 Person 如下所示:
typescriptCopy codeinterface Person {name: string;age: number;
}
接着,创建一个符合 Person 接口的对象 person1 可以简单地通过对象字面量来实现:
typescriptCopy codelet person1: Person = {name: "John",age: 30
};
在这个例子中:
person1是一个对象,它的类型被声明为Person。person1必须包含Person接口中定义的所有属性,即name(字符串类型)和age(数字类型)。
类与接口
提到类(Class),类是一种更复杂的结构,它不仅定义了对象的结构(如接口所做的那样),还包括了方法和构造函数。在 TypeScript 中,类可以实现(Implement)一个或多个接口,这意味着类中必须包含接口中定义的所有属性和方法。
创建一个符合接口 Person 的类可能是这样的:
typescriptCopy codeclass Employee implements Person {name: string;age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}
}
在这个例子中,Employee 类实现了 Person 接口。这意味着任何 Employee 的实例都将具有 Person 接口定义的结构。
尊贵的主,希望这些解释有助于您理解 TypeScript 中接口和类的区别以及如何创建符合特定接口的对象。如果您有任何其他问题或疑惑,请随时向我咨询。
You
typescripe 好像=很少用
ChatGPT
ChatGPT
尊贵的主,您的观察很有洞察力。在 TypeScript(以及现代 JavaScript)开发中,let 和 const 关键字比传统的 var 关键字更加常用,这改变了变量声明和赋值的常见模式。让我为您解释一下这些差异及其原因。
let 和 const vs var
var: 在较早的 JavaScript 版本中,var是唯一的变量声明方式。var声明的变量具有函数作用域,可能导致一些作用域相关的问题。let: 引入let是为了解决var的一些问题。let提供了块级作用域(block scope),这使得变量控制更加精确和容易。const:const也是块级作用域的,用于声明常量。一旦const变量被赋值后,其值就不能被重新赋值。
使用 = 进行赋值
- 在 TypeScript 和 JavaScript 中,
=仍然是赋值的主要方式。 - 当使用
let或const声明变量时,您可以在声明时立即使用=赋值,也可以稍后赋值。 const声明的变量必须在声明时赋值,而且之后不能改变。
例子
typescriptCopy codelet count = 10; // 使用 `let` 声明变量并赋值
count = 20; // 后续可以修改 `count` 的值const pi = 3.14; // 使用 `const` 声明常量并赋值
// pi = 3.14159; // 这将会引起错误,因为 `pi` 是常量
在 TypeScript 开发中,优先使用 const 可以确保变量值不会被意外改变,这是一种良好的实践。当变量值需要改变时,使用 let。这些实践帮助开发者写出更加清晰和可维护的代码。
尊贵的主,希望这些解释能帮助您更好地理解 TypeScript 中变量声明和赋值的使用方式。如果您有任何疑问或需要更多信息,请随时告知。
You
let person1: Person = { name: “John”, age: 30 }; 上面这种:赋值是什么方式
ChatGPT
ChatGPT
尊贵的主,您指出的这种语法结构在 TypeScript 中非常常见。在您的示例中:
typescriptCopy codelet person1: Person = {name: "John",age: 30
};
这里有两个关键部分组成:
- 类型注解(Type Annotation):
let person1: Person这部分是类型注解。: Person表明变量person1应该符合Person接口的结构。这是 TypeScript 的一个特性,用于静态类型检查。- 这告诉 TypeScript 编译器,
person1变量预期是一个Person类型的对象。
- 赋值操作(Assignment):
= { name: "John", age: 30 }这部分是对象字面量赋值。- 使用
=对person1进行赋值,赋值的内容是一个对象,这个对象包含name和age两个属性。 - 这个对象字面量符合
Person接口的结构,因此它是一个有效的赋值。
综上,这行代码的含义是:声明一个 Person 类型的变量 person1,并用一个包含 name 和 age 属性的对象初始化它。在 TypeScript 中,这种结合类型注解和赋值的做法非常常见,它提供了代码的清晰性和类型安全性。
尊贵的主,希望这个解释对您有所帮助。如果您有任何疑问或需要更多的解释,请随时告知。
You
对象字面量赋值是什么
ChatGPT
ChatGPT
尊贵的主,对象字面量赋值是一种在 JavaScript 和 TypeScript 中创建对象的方法。对象字面量是由花括号 {} 包围的一组以逗号分隔的键值对(属性名和属性值)。它允许您在一个表达式中直接定义一个对象及其属性。
对象字面量的特点
- 直接定义:您可以直接在代码中定义一个完整的对象,而不需要先声明一个空对象再逐个添加属性。
- 简洁:这种方式比逐个赋值属性更简洁,尤其是在对象包含多个属性时。
- 灵活性:对象字面量可以包含固定的属性,也可以根据需要动态计算属性名称或值。
示例
假设我们想定义一个表示人的对象,包括姓名和年龄属性。使用对象字面量赋值的方式如下:
typescriptCopy codelet person = {name: "John",age: 30
};
在这个例子中:
person是一个新创建的对象。{}内包含了两个属性:name和age。name的值是"John",age的值是30。
相比之下,如果不使用对象字面量,创建同样的对象可能需要更多步骤:
typescriptCopy codelet person = {}; // 创建一个空对象
person.name = "John"; // 逐个添加属性
person.age = 30;
使用对象字面量的方法更加直接和简洁。
尊贵的主,希望这个解释能帮助您理解对象字面量赋值的概念。如果您有任何疑问或需要进一步的解释,请随时告知。
You
第3题给我一点相关知识 我好像并没有学过
ChatGPT
ChatGPT
当然,尊贵的主,我很乐意为您解释 TypeScript 中的枚举(Enum)类型,这将帮助您完成第3题。
枚举(Enum)类型的基础
枚举是 TypeScript 提供的一种特性,用于给一组数值赋予更友好的名字。它是一种在代码中创建命名常量集合的方式。
优点
- 可读性: 枚举使代码更易于阅读和维护。通过使用具有明确名称的枚举成员,而不是裸露的数字或字符串,可以提高代码的可读性。
- 组织性: 枚举可以将一组相关的值组织在一起,使它们易于管理。
如何定义枚举
您可以通过 enum 关键字来定义一个枚举。例如:
typescriptCopy codeenum Color {Red,Green,Blue
}
在这个例子中,我们定义了一个名为 Color 的枚举,它包含三个成员:Red、Green 和 Blue。
如何使用枚举
定义枚举后,您可以像使用任何其他类型一样使用它。例如,声明一个类型为 Color 的变量,并给它赋予枚举中的一个值:
typescriptCopy code
let favoriteColor: Color = Color.Green;
在这个例子中,favoriteColor 被声明为 Color 类型,并被赋值为 Color 枚举中的 Green。
枚举的底层值
默认情况下,枚举的每个成员都会被赋予一个从零开始的数字值,但您也可以手动指定成员的值。例如:
typescriptCopy codeenum Color {Red = 1,Green,Blue
}
在这个例子中,Red 被赋予了值 1,而 Green 和 Blue 会自动被赋予 2 和 3 的值。
尊贵的主,现在您应该有足够的信息来解答第3题。如果您需要任何其他帮助或有疑问,请随时告诉我。
You
第1题: function multiply(x: number, y: number): number { if (x ===null || x === undefined || y === null || y === undefined) { return 0; } return x * y; } 第2题: interface Person { name: string; age: number; } let person1: Person = { name: "John", age: 30 } 第3题: enum Color { Red, Green, Blue } let favoriteColer: Color = Color.Green;
ChatGPT
ChatGPT
尊贵的主,您的答案非常接近完美。下面是对您的答案的评价和建议:
- 第1题: 您的答案是正确的。函数
multiply正确地接受了两个数字类型的参数,并在其中进行了null和undefined的检查。不过,您也可以简化这个检查,使用x == null || y == null来同时覆盖null和undefined的情况。 - 第2题: 完全正确。您定义了一个
Person接口,并创建了一个符合此接口的对象person1。这完全符合题目要求。 - 第3题: 您的答案也是正确的。您定义了一个名为
Color的枚举,并创建了一个Color类型的变量favoriteColor,并正确地将其设置为Color.Green。
修改建议
对于第1题,更简化的 null 和 undefined 检查:
typescriptCopy codefunction multiply(x: number | null | undefined, y: number | null | undefined): number {if (x == null || y == null) {return 0;}return x * y;
}
在这个修改中,x == null || y == null 会同时检查 null 和 undefined,使代码更为简洁。
尊贵的主,您在 TypeScript 的学习上已经取得了显著的进步。如果您有任何疑问,或者想要继续进行练习,请随时告知。我在此为您提供帮助。