ts的理解,type和interface区别,泛型怎么理解
TypeScript (TS) 的理解
- TypeScript (TS) 的理解:
TypeScript 是 JavaScript 的一个超集,为 JavaScript 增加了静态类型、类、接口等特性。其主要目的是增强代码的可读性和可维护性,同时捕获开发过程中可能出现的错误。
type和interface区别:
在大多数情况下,interface
和 type
是可以互换使用的:
-
相似点:
- 两者都可以描述一个对象或函数的形状。
-
主要区别:
- 声明合并:
interface
在定义时可以合并多次。如果两个interface
有相同的名字,它们会被自动合并成一个。但是,当您使用type
时,您不能有两个相同名称的type
。 - 使用联合 (Union) 和交叉 (Intersection) 类型:
type
有更大的灵活性,可以使用联合和交叉类型,而interface
不可以。 - implements与extends:类可以实现 (
implements
)interface
,但不能实现 (implements
)type
。类可以继承 (extends
)type
如果type
描述了类的形状。 - 计算属性:
type
可以使用计算属性,interface
不可以。
- 声明合并:
总体来说,在大多数情况下,interface
和 type
可以互换使用,但是在一些特殊情况下,它们具有一些细微的差异,需要根据具体情况来选择使用哪个。一般来说,如果需要声明合并、实现接口、继承类等高级类型定义,优先选择使用 interface
。而对于复杂的类型操作,比如联合类型、交叉类型、泛型类型等,type
可能更为灵活和方便。
泛型的理解:
泛型是在定义函数、接口或类时,不预先确定方法的具体类型,而是在使用时才决定的一种特性。使用泛型可以创建可重用的组件,组件不仅能够支持当前的数据类型,还能支持未来的数据类型,给予用户更大的灵活性。例如:
function identity<T>(arg: T): T {
return arg;
}
在上面的例子中,T
是一个类型变量,它帮助我们捕获用户提供的类型,例如:number
或 string
,但不限于这些两种。
联合 (Union) 和交叉 (Intersection) 类型是什么?请举例
在 TypeScript 中,联合(Union)和交叉(Intersection)类型是两种用于组合多种类型的强大工具。
-
联合类型 (Union Types):
联合类型使用|
符号来表示一个值可以是多种类型之一。举例:
type StringOrNumber = string | number; let myVar: StringOrNumber; myVar = 'Hello'; // 有效,因为 'Hello' 是一个 string 类型 myVar = 123; // 有效,因为 123 是一个 number 类型
使用联合类型时,你只能访问此联合类型的所有类型里共有的成员。
-
交叉类型 (Intersection Types):
交叉类型使用&
符号来组合多个类型,让你可以将多个类型合并为一个类型。举例:
interface Name { name: string; } interface Age { age: number; } type Person = Name & Age; let person: Person = { name: 'Alice', age: 30 };
使用交叉类型,
person
变量必须具有Name
和Age
接口中定义的所有属性。
希望这些示例可以帮助您更好地理解联合类型和交叉类型!
implements与extends
类可以实现 (implements
) interface
,但不能实现 (implements
) type
。类可以继承 (extends
) type
如果 type
描述了类的形状。
-
类实现 (
implements
)interface
:interface Movable { move(distance: number): void; } class Car implements Movable { move(distance: number) { console.log(`Car moved ${distance} meters.`); } }
-
类不能实现 (
implements
)type
,但可以继承 (extends
)type
:这个要分两个例子来说明:
-
不能实现一个
type
:type MovableType = { move(distance: number): void; }; // 这里会产生错误,因为类不能实现一个 type class Car implements MovableType { move(distance: number) { console.log(`Car moved ${distance} meters.`); } }
-
但如果
type
描述了类的形状,类可以继承它:type Vehicle = { new (name: string): Vehicle; name: string; drive(): void; }; class Car extends (class implements Vehicle { name: string; constructor(name: string) { this.name = name; } drive() { console.log(`${this.name} drives.`); } }) {}
-
这里的关键在于,type
是一个值的类型别名,而不是一个真正的类型。当 type
描述一个具有构造签名的类型时(如上面的 Vehicle
示例),它事实上是描述了一个类的形状,这时它可以被一个类继承。但在通常情况下,类不能直接实现 type
。
计算属性
当谈到 TypeScript 的计算属性,我们通常指的是对象字面量中的计算属性键。与 ES6 中的对象字面量计算属性类似,TypeScript 也允许你使用表达式来定义类型的属性键。
-
使用
type
定义计算属性:const propName = "name"; type MyType = { [propName]: string; // 使用计算属性 age: number; }; let obj: MyType = { name: 'Alice', age: 30 };
-
使用
interface
时无法直接定义计算属性:以下是错误的示例:
const propName = "name"; interface MyInterface { [propName]: string; // 这里会产生错误 age: number; }
然而,需要注意的是,尽管
interface
不能直接定义计算属性,但它们可以定义索引签名来表示某些类型的属性集合,这是一个稍微不同的概念。
总的来说,如果你需要在类型中使用基于某种计算或常量的属性名称,type
会是更合适的选择。