- TypeScript 基础
- TypeScript - 首页
- TypeScript - 路线图
- TypeScript - 概述
- TypeScript - 环境设置
- TypeScript - 基本语法
- TypeScript vs. JavaScript
- TypeScript - 特性
- TypeScript - 变量
- TypeScript - let & const
- TypeScript - 运算符
- TypeScript 基本类型
- TypeScript - 类型
- TypeScript - 类型注解
- TypeScript - 类型推断
- TypeScript - 数字
- TypeScript - 字符串
- TypeScript - 布尔值
- TypeScript - 数组
- TypeScript - 元组
- TypeScript - 枚举
- TypeScript - any
- TypeScript - never
- TypeScript - 联合类型
- TypeScript - 字面量类型
- TypeScript - Symbol
- TypeScript - null vs. undefined
- TypeScript - 类型别名
- TypeScript 控制流
- TypeScript - 决策
- TypeScript - if 语句
- TypeScript - if else 语句
- TypeScript - 嵌套 if 语句
- TypeScript - switch 语句
- TypeScript - 循环
- TypeScript - for 循环
- TypeScript - while 循环
- TypeScript - do while 循环
- TypeScript 函数
- TypeScript - 函数
- TypeScript - 函数类型
- TypeScript - 可选参数
- TypeScript - 默认参数
- TypeScript - 匿名函数
- TypeScript - Function 构造函数
- TypeScript - rest 参数
- TypeScript - 参数解构
- TypeScript - 箭头函数
- TypeScript 接口
- TypeScript - 接口
- TypeScript - 接口扩展
- TypeScript 类和对象
- TypeScript - 类
- TypeScript - 对象
- TypeScript - 访问修饰符
- TypeScript - 只读属性
- TypeScript - 继承
- TypeScript - 静态方法和属性
- TypeScript - 抽象类
- TypeScript - 存取器
- TypeScript - 鸭子类型
- TypeScript 高级类型
- TypeScript - 交叉类型
- TypeScript - 类型守卫
- TypeScript - 类型断言
- TypeScript 类型操作
- TypeScript - 从类型创建类型
- TypeScript - keyof 类型操作符
- TypeScript - typeof 类型操作符
- TypeScript - 索引访问类型
- TypeScript - 条件类型
- TypeScript - 映射类型
- TypeScript - 模板字面量类型
- TypeScript 泛型
- TypeScript - 泛型
- TypeScript - 泛型约束
- TypeScript - 泛型接口
- TypeScript - 泛型类
- TypeScript 其他
- TypeScript - 三斜杠指令
- TypeScript - 命名空间
- TypeScript - 模块
- TypeScript - 环境声明
- TypeScript - 装饰器
- TypeScript - 类型兼容性
- TypeScript - Date 对象
- TypeScript - 迭代器和生成器
- TypeScript - Mixin
- TypeScript - 实用程序类型
- TypeScript - 装箱和拆箱
- TypeScript - tsconfig.json
- 从 JavaScript 到 TypeScript
- TypeScript 有用资源
- TypeScript - 快速指南
- TypeScript - 有用资源
- TypeScript - 讨论
TypeScript - 类型兼容性
在 TypeScript 中,类型兼容性是指将一种类型的变量、对象等赋值给另一种类型的能力。换句话说,它指的是根据类型的结构检查两种类型是否兼容的能力。
例如,字符串和布尔类型彼此不兼容,如下面的代码所示。
let s:string = "Hello"; let b:boolean = true; s = b; // Error: Type 'boolean' is not assignable to type 'string' b = s; // Error: Type 'string' is not assignable to type 'boolean'
TypeScript 的类型系统允许执行编译时不安全的某些操作。例如,任何类型的变量都与 'any' 类型兼容,这是不安全的行为。
例如:
let s: any = 123; s = "Hello"; // Valid
TypeScript 如何执行类型兼容性检查?
Typescript 使用结构化子类型和结构化赋值来执行类型兼容性检查。让我们通过示例学习每一个。
结构化子类型
TypeScript 使用结构化子类型方法来检查特定类型是否为另一种类型的子类型。即使特定类型的成员名称不匹配,但结构匹配,TypeScript 编译器也会将这两种类型视为相同。
例如:
interface Person { name: string; } let person: Person; let obj = { name: "John", age: 30 }; // Ok person = obj;
要检查 'obj' 对象的类型是否与 Person 接口的类型兼容,typescript 会检查 'obj' 是否至少包含 Person 接口中包含的所有属性和方法。
TypeScript 不关心添加到子类型的额外成员。这里,obj 对象包含一个额外的 'age' 属性,但它仍然与 Person 类型兼容,因为 obj 对象包含字符串类型的 'name' 属性。
如果 'obj' 对象不包含 Person 接口的所有成员,则它不能赋值给具有 Person 类型的对象。例如:
interface Person { name: string; } let person: Person; let obj = { n: "John", age: 30 }; // Not Ok person = obj;
当我们编译上述代码时,它会抛出错误,因为 'obj' 对象的类型与 Person 接口不同。
如何有效地使用类型兼容性?
开发人员可以使用接口和泛型来有效地在 TypeScript 中使用类型。以下是使用接口和泛型进行类型兼容性的最佳技巧。
使用接口
使用接口,开发人员可以定义契约或类型,以确保实现符合这些类型。这有助于确保代码不同部分之间的类型兼容性。
让我们通过下面的示例来了解它。
示例
在下面的示例中,'user2' 变量的类型为 'User'。因此,开发人员可以将具有与 'User' 接口相同属性的对象赋值给 'user2' 对象。
interface User { name: string; age: number; } const user = { name: "Alice", age: 30 }; let user2: User = user; console.log(user2)
编译后,它将生成以下 JavaScript 代码。
const user = { name: "Alice", age: 30 }; let user2 = user; console.log(user2);
输出
其输出如下:
{ name: 'Alice', age: 30 }
使用泛型
我们可以使用泛型来创建可重用的组件,这些组件可以与多种数据类型一起工作,而不是单一数据类型。它允许开发人员将类型作为参数传递,并将其用于变量、对象、类、函数参数等。
让我们通过下面的示例来了解它。
示例
在下面的代码中,我们有一个 'Wrapper' 接口,它将数据类型作为参数。我们创建了 stringWrapper 和 numberWrapper 变量,并将字符串和数字数据类型作为参数传递。
// Define a generic interface with a single property interface Wrapper<T> { value: T; } // Use the interface with a string type let stringWrapper: Wrapper<string> = { value: "Hello, TypeScript!", }; // Use the interface with a number type let numberWrapper: Wrapper<number> = { value: 123, }; console.log(stringWrapper.value); // Output: Hello, TypeScript! console.log(numberWrapper.value); // Output: 123
编译后,它将生成以下 JavaScript 代码。
// Use the interface with a string type let stringWrapper = { value: "Hello, TypeScript!", }; // Use the interface with a number type let numberWrapper = { value: 123, }; console.log(stringWrapper.value); // Output: Hello, TypeScript! console.log(numberWrapper.value); // Output: 123
输出
上述示例代码将产生以下输出:
Hello, TypeScript! 123
函数和类型兼容性
当我们比较或将一个函数赋值给另一个函数时,TypeScript 编译器会检查目标函数是否至少具有与源函数相同的参数和返回类型。如果您将函数 'x' 赋值给函数 'y',则函数 'x' 是目标函数,函数 'y' 是源函数。函数 'y' 中的附加参数不会导致任何错误。
示例
在下面的代码中,函数 'x' 只包含 1 个参数,而函数 'y' 包含 2 个参数。当我们将函数 'x' 赋值给函数 'y' 时,附加参数 's' 不会导致任何错误。
// Defining functions let x = (a: number) => { console.log(a); }; let y = (b: number, s: string) => { console.log(b + s); }; y = x; // OK // x = y; // Error: x does not accept two arguments.
类和类型兼容性
当我们比较两个类时,它只比较实例的成员。类构造函数和静态成员属于类本身,因此它们不包含在比较中。
示例
在此代码中,变量 'a' 和变量 'b' 具有相同的实例成员。因此,当我们将变量 'a' 赋值给 'b' 时,它不会引发任何错误。
class Animal { feet: number; constructor(name: string, numFeet: number) {} } class Size { feet: number; constructor(meters: number) {} } let a: Animal; let s: Size; // Works because both classes have the same shape (they have the same instance properties). a = s;
您可以使用接口和泛型进行类型兼容性。对于函数,目标函数应该至少具有与源函数相同的参数。对于类的类型兼容性,它们应该具有相同的实例成员。