文章目录
TypeScript的优势
TypeScript提供了静态类型检查、面向对象编程能力的增强、更好的工具支持等一系列优势。以下是对TypeScript主要优势的详细分析:
- 类型安全:TypeScript通过静态类型检查,能够在编译时发现潜在错误,减少运行时错误,从而提高代码的可靠性。
- 更好的IDE支持:TypeScript的类型信息使得现代编辑器(如VS Code)能够提供更丰富的智能提示和代码补全功能,显著提高开发效率。
- 代码可维护性:TypeScript鼓励使用接口和类型定义,使得大型项目的代码更易于维护和扩展。
- 生产力工具的提升:TypeScript与VS Code等工具的集成,提供了代码自动完成、重构工具、静态分析工具等,进一步提升开发效率。
- 静态代码分析能力:解决原先在运行时(runtime)JavaScript无法发现的错误,通过静态分析提高代码质量。
- 易于项目后期维护、重构:当版本迭代时,TypeScript的编译器会给予警告或错误提示,帮助开发者保持代码的一致性和稳定性。
TypeScript与JavaScript的对比
- JavaScript的优势:简单易学,广泛支持,丰富的生态系统。
- TypeScript的劣势:学习曲线相对陡峭,配置和编译过程更为复杂。
TypeScript通过其静态类型系统和强大的工具支持,为开发者提供了一个更加可靠、高效的开发环境。尤其是在大型项目和团队协作中,TypeScript的优势更加明显。
和 JavaScript 的区别
Typescript 是 JavaScript 的超集,可以被编译成 JavaScript 代码。 用 JavaScript 编写的合法代码,在 TypeScript 中依然有效。Typescript 是纯面向对象的编程语言,包含类和接口的概念。 程序员可以用它来编写面向对象的服务端或客户端程序,并将它们编译成 JavaScript 代码。
TypeScript和 JavaScript的关系
TypeScript 引入了很多面向对象程序设计的特征,包括:
interfaces 接口
classes 类
enumerated types 枚举类型
generics 泛型
modules 模块
主要不同点如下:
TS 是一种面向对象编程语言,而 JS 是一种脚本语言(尽管 JS 是基于对象的)。
TS 支持可选参数, JS 则不支持该特性。
TS 支持静态类型,JS 不支持。
TS 支持接口,JS 不支持接口。
unknown和any区别
在 TypeScript 中,unknown
和 any
都可以用来表示未知类型的值,但它们在类型安全方面有很大的不同。
any
any
是 TypeScript 中的一个特殊类型,它表示任何 JavaScript 值。当你使用 any
类型时,TypeScript 编译器会关闭对该值的类型检查,这意味着你可以对该值执行任何操作,而不会收到编译错误。这可能会导致潜在的运行时错误,因为类型检查被绕过了。
let value: any = "Hello, World!";
value = 42; // 可以赋值为任何类型
unknown
unknown
是 TypeScript 中的一个更安全的未知类型。与 any
不同,当你使用 unknown
类型时,TypeScript 编译器会对该值进行类型检查。你不能对 unknown
类型的值执行任何操作,除非你先对其进行类型断言或类型检查。
let value: unknown = "Hello, World!";
// value.toUpperCase(); // 错误:不能对 unknown 类型的值调用方法
if (typeof value === "string") {
value.toUpperCase(); // 正确:先进行类型检查
}
总结
any
类型会关闭类型检查,可能导致潜在的运行时错误。unknown
类型在编译时进行类型检查,更安全,但需要显式地进行类型断言或类型检查。
在实际开发中,推荐使用 unknown
类型,因为它提供了更好的类型安全性。只有在确实需要绕过类型检查的情况下,才使用 any
类型。
type 和 interface
- 用interface描述数据结构,用type描述类型
- type 可以声明基本类型别名,联合类型,元组等类型
在 TypeScript 中,type
和 interface
都是用来定义对象类型的方式,但它们之间有一些重要的区别:
type
type
关键字可以用来定义一个对象的形状,也可以用来定义联合类型、交叉类型、元组等。
type Person = {
name: string;
age: number;
};
type StringOrNumber = string | number;
interface
interface
关键字也用来定义对象的形状,但与 type
不同的是,interface
可以被声明合并(declaration merging),这意味着如果你多次声明同一个接口,它们会被合并成一个接口。
interface Person {
name: string;
age: number;
}
// 在另一个地方
interface Person {
address: string;
}
// 最终的 Person 接口会是这样
interface Person {
name: string;
age: number;
address: string;
}
区别
- 声明合并:如上所述,
interface
支持声明合并,而type
不支持。 - 联合类型:
type
可以定义联合类型(如上面的StringOrNumber
),而interface
不能。 - 实现:类可以实现(implements)接口,但不能实现类型别名。
- 扩展:
interface
可以通过extends
关键字来扩展其他接口,而type
可以通过交叉类型来达到类似的效果。
使用建议
- 如果你需要定义一个可以被类实现的接口,或者你需要使用声明合并,那么应该使用
interface
。 - 如果你需要定义联合类型、交叉类型,或者你不需要声明合并的功能,那么可以使用
type
。
总的来说,type
和 interface
都是 TypeScript 中定义类型的重要工具,选择使用哪一个取决于你的具体需求。
泛型
- 泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,使用时再去指定类型的一种特性。可以把泛型理解为代表类型的参数。
interface Test<T = any> {
userId: T;
}
type TestA = Test<string>;
type TestB = Test<number>;
const a: TestA = {
userId: '111',
};
const b: TestB = {
userId: 2222,
};
ts类
Typescript是一种面向对象的Javascript语言,和其他任何面向对象编程的强语言一样,类是描述某一组对象共有属性状态或行为的实体。它就是构建具体对象实例的模板和蓝图。
特性:
1:继承
2:多态
3:抽象
4:封装
5:实例
Pick
从一个已存在的类型中“挑选”出一个或多个属性,创建一个新的类型。这对于类型映射、条件类型以及创建基于现有类型的新类型时非常有用。
Pick类型的基本语法如下:
type Pick<T, K extends keyof T> = {
[P in K]: TP;
};
T 是原始类型,K 是 T 的属性名的集合(通过 keyof T 获取),Pick 创建一个新的类型,这个新类型只包含 K 中指定的属性。
使用示例
假设我们有如下的TypeScript接口:
interface Person {
name: string;
age: number;
location: string;
}
如果我们只想从一个 Person 类型的对象中选取 name 和 age 属性,我们可以这样做:
type PersonDetails = Pick<Person, 'name' | 'age'>;
// 现在 PersonDetails 类型等价于:
// type PersonDetails = {
// name: string;
// age: number;
// }
const personDetails: PersonDetails = {
name: 'Alice',
age: 30,
// 如果尝试添加 location 属性,TypeScript 将报错,因为 PersonDetails 不包含该属性
// location: 'New York'
};
实际应用
Pick 在处理复杂类型映射时非常有用,特别是在结合其他工具类型(如 Omit、Partial、Required 等)时。例如,你可能有一个复杂的对象,但只需要其部分属性用于某个特定的函数或组件。通过使用 Pick,你可以轻松地创建一个仅包含所需属性的新类型,从而保持类型安全和代码清晰度。
注意事项
Pick 中的 K 必须是 T 的有效键名集合。如果尝试选取 T 中不存在的属性,TypeScript 将报错。
Pick 创建的类型是静态的,即在编译时确定。它不会根据运行时的数据动态改变。
Pick 是TypeScript类型系统中一个非常强大的工具,能够帮助你以类型安全的方式处理复杂的类型映射问题。
在TypeScript中,Omit、Partial、Required 是三个非常有用的内置工具类型,它们允许你以声明式的方式修改现有类型的属性。这些工具类型在类型映射、条件类型以及复杂类型操作中特别有用。
Omit
Omit<T, K>
从一个对象类型中排除某些属性,把剩下的组成新类型。这个新类型包含 T 中除了 K 指定的属性之外的所有属性。
语法:
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
(注意:上面的 Omit 定义是基于 Pick 和 Exclude 的,但实际上在TypeScript中是直接提供的。)
示例:
interface Person {
name: string;
age: number;
location: string;
}
type PersonWithoutLocation = Omit<Person, 'location'>;
// 现在 PersonWithoutLocation 类型等价于:
// type PersonWithoutLocation = {
// name: string;
// age: number;
// }
Partial
Partial<T>
Partial 工具类型将类型 T 的所有属性变为可选的(即属性后加上 ?)。这意味着你可以省略这些属性,或者为它们提供值。
语法:
type Partial<T> = {
[P in keyof T]?: T[P];
};
示例:
interface Person {
name: string;
age: number;
}
type PartialPerson = Partial<Person>;
// 现在 PartialPerson 类型等价于:
// type PartialPerson = {
// name?: string;
// age?: number;
// }
Required
Required<T>
与 Partial 相反,Required 工具类型将类型 T 的所有属性变为必需的(即移除所有属性后的 ?)。这在你想要确保一个对象具有所有必需的属性时非常有用。
语法:
type Required<T> = {
[P in keyof T]-?: T[P];
};
(注意:-? 语法是TypeScript特有的,用于移除可选性。)
示例:
interface PartialPerson {
name?: string;
age?: number;
}
type RequiredPerson = Required<PartialPerson>;
// 现在 RequiredPerson 类型等价于:
// type RequiredPerson = {
// name: string;
// age: number;
// }
Readonly
将类型转化为只读
export interface Contact{
readonly name: string; // 赋值后姓名不可修改
phone?: string; // 手机号
email: string; // 邮箱
avatar: string; // 头像
userid: string; // id
}
Readonly源码实现
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Exclude
Exclude (排除/不包括),一般用于处理联合类型
Exclude源码
type Exclude<T, U> = T extends U ? never : T;
处理联合类型
type Test1 = '1' | '2' | '3'
const obj: Exclude<Test1, '1' | '2'> = '3'; // 3 OK 赋值1,2就会error
Extract
Extract (提取/包括),和 Exclude 正好相反,也是用于处理联合类型
Extract实现源码
type Extract<T, U> = T extends U ? T : never;
// 处理联合类型
type Test1 = '1' | '2' | '3'
const obj: Extract<Test1, '1' | '2'> = '1'; // 1,2 OK 赋值3就会error
ReturnType
ReturnType (函数的类型推导返回)
ReturnType源码
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
ReturnType案例
// 正确用法
const myFun = () => ({
name: 'zhangsan',
age: 233,
sex: '1',
tel: 123456789,
fun: () => {
return 233;
},
arr: [1,2,3,4,5,6]
});
type Test2 = ReturnType<typeof myFun>; // OK 鼠标放到Test2上可以发现 已推导出了myFun函数的返回类型。
// 错误用法
const someValue = 42;
type InvalidReturnType = ReturnType<typeof someValue>; // error错误!someValue 不是一个函数。
NonNullable
NonNullable (类型中排除 null 和 undefined)
源码
type NonNullable<T> = T & {};
泛型参数T和{}的交集就默认排除了null
和 undefined
NonNullable的使用案例
type MaybeString = string | null | undefined;
const value: MaybeString = getSomeStringValue(); // 假设这个函数可能返回一个字符串、null 或 undefined
// 使用 NonNullable 确保 value 不会是 null 或 undefined
const nonNullableValue: NonNullable<MaybeString> = value!; // 使用 ! 断言操作符,或者通过其他方式确保值不为 null 或 undefined
// 现在,nonNullableValue 的类型是 string,因为我们已经排除了 null 和 undefined
console.log(nonNullableValue.length); // 这是安全的,因为我们知道 nonNullableValue 一定是字符串
// 其实就是某些场景绝对为了排除null,undefined的类型才用的
在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非 undefined类型。具体而言,x! 将从 x 值域中排除 null 和 undefined 。
注意事项
这些工具类型都是在编译时解析的,不会影响运行时的JavaScript代码。
它们都是TypeScript语言的一部分,因此你不需要安装任何额外的库来使用它们。