2. type的用法
约 1785 字大约 6 分钟
2025-05-14
总结
- 类型别名可以给任何已知的类型、类型的组合起别名。
- 类型别名只是一个已知类型的引用,不会新建一个类型。
- 类型别名不允许重复定义,会报错。
- 类型别名一旦定义,就不能修改。
- 类型别名可以使用
&
扩展新的字段,形成新的类型。 - 类型别名可以嵌套使用,形成新的类型。
- 类型别名支持块状作用域。
- 类型别名可以被接口继承。
一、简介
type
是 TypeScript 中的一个关键字,用于定义类型别名。它可以给任何类型起别名,包括基本类型、包装类型,甚至于交叉类型、联合类型、甚至字面量类型等。
类型别名有啥好处:
- 类型别名可以简化复杂类型的定义,提高了代码可维护性
- 类型别名可以使用语义性比较强的名称,大大提高了代码可读性
- 一次定义,多处使用,减少代码冗余、提高代码复用率。
- 类型别名可以通过交叉
&
扩展成一个新类型,可扩展性高。
二、基础用法
type
可以定义基础类型、对象类型、函数类型、字面量类型、交叉类型、联合类型等。
以下是一个比较全面的 type
用法示例:
// number 类型
type Age = number;
// string 类型
type Name = string;
// boolean 类型
type IsAdult = boolean;
// 元组类型
type Address = [string, string, string];
// 联合类型 + 字面量类型
type Skill_Level = "初级" | "中级" | "高级";
// 对象类型
type Skill = {
name: string;
level: Skill_Level;
};
// 数组类型
type Skills = Skill[];
class Person {
name: Name;
isAdult: IsAdult;
skills: Skills;
address: Address;
}
// class 类型
type Ren_Def = Person;
// 函数类型 1
type Walk = (name: string) => void;
// 函数类型 2
type Speak = {
(name: string): string;
};
type Ren_Age = {
age: Age;
walk: Walk;
speak: Speak;
};
// 交叉类型
type Ren = Ren_Def & Ren_Age;
interface Man extends Ren {
// 字面量类型
sex: "male";
}
interface Woman extends Ren {
// 字面量类型
sex: "female";
}
// 接口类型
type NanRen = Man;
// 接口类型
type NvRen = Woman;
const user: NanRen = {
name: "Alice",
age: 20,
isAdult: true,
sex: "male",
skills: [
{
name: "JavaScript",
level: "中级",
},
],
address: ["China", "Shanghai", "Xinjiang Road"],
walk: function (name: string): void {
console.log(`${name} is walking.`);
},
speak: function (name: string): string {
return `${name} is speaking.`;
},
};
三、高级特性
1、可选属性
可选属性是指在定义对象类型时,可以选择是否给属性赋值。可选属性使用 ?
来表示。
type User = {
id: number;
name: string;
age?: number; // 可选属性
};
const user: User = {
id: 1,
name: "Alice",
age: 30, // 可选属性可以不赋值
};
2、只读属性
只读属性是指在定义对象类型时,属性的值不能被修改。只读属性使用 readonly
来表示。
type Man = {
readonly sex: Stirng;
name: string;
};
const man: Man = {
sex: "male",
name: "Alice",
};
type Man = {
readonly sex: string;
name: string;
};
const man: Man = {
sex: "male",
name: "Alice",
};
man.sex = "1"; // 报错
man.name = "Bob"; // 正常
3、属性索引签名
属性索引签名是指在定义对象类型时,可以使用索引签名来定义对象的属性。索引签名使用 [key: string]: type
来表示。
type User = {
[key: string]: any; // 索引签名
};
const user: User = {
id: 1,
name: "Alice",
age: 30,
address: "China",
};
4、属性扩展
类型别名可以使用 &
扩展新的字段,形成新的类型,这也是交叉类型常见一个用法。
type User = {
id: number;
name: string;
};
type UserInfo = User & {
age: number;
};
const user: UserInfo = {
id: 1,
name: "Alice",
age: 30,
};
5、嵌套
类型别名可以嵌套使用,形成新的类型。
type World = "world";
type Greeting = `hello ${World}`;
const greeting: Greeting = "hello world";
6、块状作用域
类型别名可以在代码块中定义,形成局部作用域。
type Temp = string;
if (Math.random() < 0.5) {
type Temp = number;
const a: Temp = 1234;
}
const b: Temp = "abcd";
四、其他特性
1、可以被接口继承
type User = {
name: string;
};
interface Man extends User {
age: number;
}
const user: Man = {
name: "123",
age: 123,
};
2、定义函数类型
type
可以用来定义函数类型,包括函数的参数类型和返回值类型。
// 写法 1
type Add = (a: number, b: number) => number;
const add: Add = (a, b) => a + b;
// 写法 2
type Subtract = {
(a: number, b: number): number;
};
const subtract: Subtract = (a, b) => a - b;
3、定义构造函数类型
type
可以用来定义构造函数类型,包括构造函数的参数类型和返回值类型。
// 定义一个构造函数类型
type UserConstructor = new (name: string, age: number) => User;
// 和构造函数结构相同的类
class User {
constructor(public name: string, public age: number) {}
}
// 用于动态创建用户实例的函数
function createUser(ctor: UserConstructor, name: string, age: number): User {
return new ctor(name, age);
}
// 生成一个用户实例
const john = createUser(User, "John", 30);
4、可以被 Class 类实现
type Country = {
name: string;
capital: string;
};
class MyCountry implements Country {
name = "";
capital = "";
}
五、与 interface
的区别
1、定义
type
是 TypeScript 中的一个关键字,用于定义类型别名。它可以给任何类型起别名,包括基本类型、包装类型,甚至于交叉类型、联合类型、甚至字面量类型等。
接口interface
主要用于定义对象的成员属性和方法。这个对象可以是 Object、Array。也可以用作函数和构造函数的定义。
2、type
和接口的区别
类型别名和接口的区别如下:
- 类型别名可以给任何已知的类型、类型的组合起别名,而接口只能给对象类型起别名。
- 类型别名只是一个已知类型的引用,不会新建一个类型,而接口会新建一个类型。
- 类型别名不允许重复定义,而接口可以重复定义。
- 类型别名可以使用
&
扩展新的字段,形成新的类型,而接口只能使用extends
继承新的字段,形成新的类型。 - 类型别名可以嵌套使用,而接口不能嵌套使用。
- 类型别名支持块状作用域,而接口不支持块状作用域。
- 类型别名可以被接口继承,而接口不能被类型别名继承。
3、使用场景
类型别名和接口的使用场景如下:
- 如果需要给已知的类型起别名,使用类型别名。
- 如果需要给对象类型起别名,使用接口。
- 如果需要给函数类型起别名,使用类型别名。
- 如果需要给数组类型起别名,使用类型别名。
- 如果需要给元组类型起别名,使用类型别名。
- 如果需要给交叉类型起别名,使用类型别名。
- 如果需要给联合类型起别名,使用类型别名。
- 如果需要给字面量类型起别名,使用类型别名。
- 如果需要给对象的属性和方法起别名,使用接口。
- 如果需要给数组的元素类型起别名,使用接口。
- 如果需要给函数的参数和返回值起别名,使用接口。
- 如果需要给类的属性和方法起别名,使用接口。
- 如果需要给类的构造函数起别名,使用接口。
以上是类型别名和接口的区别和使用场景。
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于