盘点 TypeScript 内置类型
当开发者开始学习 TypeScript 时,了解和理解内置类型是一个重要的步骤。TypeScript 提供了一系列内置类型,这些类型可以帮助我们更好地定义和使用变量、函数和对象。
首先,TypeScript 提供了基本的原始类型,包括 number
、string
、boolean
、null
和 undefined
。这些类型可以用来声明变量的基本数据类型。
此外,TypeScript 还提供了一些更高级的内置类型,例如 Array
、Tuple
、Enum
和 Any
。Array
类型用于定义数组,Tuple
类型用于定义具有固定长度和特定类型的数组。Enum
类型用于定义枚举类型,它允许我们为一组相关的常量赋予一个更友好的名称。Any
类型是 TypeScript 中的顶级类型,它允许我们在编译时不进行类型检查。
TypeScript 还引入了一些更复杂的内置类型,例如 Object
、Function
和 Promise
。Object
类型用于描述非原始类型的变量,Function
类型用于描述函数,Promise
类型用于处理异步操作的结果。
此外,TypeScript 还提供了一些有用的内置类型,如 Date
、RegExp
和 Error
。Date
类型用于处理日期和时间,RegExp
类型用于处理正则表达式,Error
类型用于处理错误。
最后,TypeScript 还支持一些高级的类型操作符和类型推断,例如 union
、intersection
、type assertion
和 type inference
。这些功能使得在 TypeScript 中定义和使用复杂类型变得更加灵活和强大。
了解和熟悉这些内置类型对于编写健壮、可维护和类型安全的 TypeScript 代码至关重要。通过合理地使用这些类型,我们可以在开发过程中更好地捕获错误、提高代码质量并减少调试时间。
本文将带大家了解 TypeScript 的一些高级类型的使用以及它的实现。
Partial
Partial
用于将给定类型的所有属性设置为可选。换句话说,Partial
可以创建一个新的类型,该类型具有与原始类型相同的属性,但是这些属性都是可选的。
使用 Partial
可以很方便地定义一个对象,其中的属性可以选择性地进行赋值。这对于需要根据上下文动态设置对象属性的情况非常有用,或者当你想只更新对象的一部分属性时。
下面是一个例子,演示了如何使用 Partial
类型工具:
typescript
interface User {
name: string;
age: number;
email: string;
}
function updateUser(user: Partial<User>): void {
// 更新用户信息
// ...
}
const user: User = {
name: "John",
age: 30,
email: "john@example.com"
};
updateUser({ name: "John Doe" }); // 仅更新名称
updateUser({ age: 31, email: "john.doe@example.com" }); // 仅更新年龄和邮箱
在上面的例子中,我们定义了一个 User
接口,它具有 name
、age
和 email
属性。然后,我们定义了一个 updateUser
函数,它接受一个 Partial<User>
类型的参数,即一个部分完成的 User
对象。
通过使用 Partial<User>
,我们可以在调用 updateUser
函数时,只传递需要更新的属性,而不需要提供完整的 User
对象。这使得我们可以轻松地只更新用户的某些属性,而不必修改其他属性。
总之,Partial
类型工具是 TypeScript 中的一个有用工具,它可以帮助我们定义具有可选属性的对象类型,并在需要时方便地更新对象的部分属性。
下面我们来看看它的实现:
typescript
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Partial<T>
:通过type
关键字定义了一个泛型类型Partial<T>
,其中T
是一个类型参数,表示待处理的类型。[P in keyof T]?
:使用索引类型查询操作符keyof T
获取类型T
的所有属性,并使用in
关键字遍历这些属性。P
是遍历过程中的属性名,[P in keyof T]
表示在新类型中创建一个属性,属性名为P
。?: T[P]
:使用可选属性操作符?
将属性的值变为可选的。T[P]
表示在新类型中定义的属性的类型与原类型T
对应属性的类型相同。
综合起来,Partial<T>
的作用是将类型 T
的所有属性转换为可选属性,即每个属性都可以有值或者不设置值。这个类型在实际开发中常用于对对象进行部分更新或者扩展,方便进行属性的选择性赋值。
Required
Required
用于将给定类型的所有属性设置为必需的。换句话说,Required
可以创建一个新的类型,该类型具有与原始类型相同的属性,但是这些属性都是必需的,不能省略。
使用 Required
可以很方便地定义一个对象,其中的属性必须进行赋值。这对于确保对象的完整性和类型安全非常有用。
下面是一个例子,演示了如何使用 Required
类型工具:
typescript
interface User {
name?: string;
age?: number;
email?: string;
}
function createUser(user: Required<User>): void {
// 创建用户
// ...
}
createUser({ name: "John", age: 30, email: "john@example.com" }); // 完整的用户信息
createUser({ name: "John" }); // 缺少必需的属性,会报错
在上面的例子中,我们定义了一个 User
接口,它具有 name
、age
和 email
属性,但是这些属性都是可选的,即可以省略。然后,我们定义了一个 createUser
函数,它接受一个 Required<User>
类型的参数,即一个必需的 User
对象。
通过使用 Required<User>
,我们可以确保在调用 createUser
函数时,必须提供完整的 User
对象,而不能省略任何必需的属性。这有助于保证创建的用户对象具有所需的完整性和类型安全。
下面我们来看看它的实现:
typescript
/**
* Make all properties in T required
*/
type Required<T> = {
[P in keyof T]-?: T[P];
};
type Required<T>
:通过type
关键字定义了一个泛型类型Required<T>
,其中T
是一个类型参数,表示待处理的类型。[P in keyof T]-?
:使用索引类型查询操作符keyof T
获取类型T
的所有属性,并使用in
关键字遍历这些属性。P
是遍历过程中的属性名,[P in keyof T]
表示在新类型中创建一个属性,属性名为P
。-?: T[P]
:使用必选属性操作符-?
将属性的值变为必选的。T[P]
表示在新类型中定义的属性的类型与原类型T
对应属性的类型相同。
综合起来,Required<T>
的作用是将类型 T
的所有属性转换为必选属性,即每个属性都必须有值。这个类型在实际开发中常用于对对象进行必要属性的约束,确保属性的完整性和正确性。
Readonly
Readonly
用于将给定类型的所有属性设置为只读。换句话说,Readonly
可以创建一个新的类型,该类型具有与原始类型相同的属性,但是这些属性都是只读的,不能被修改。
使用 Readonly
可以很方便地定义一个只读的对象,其中的属性不能被修改。这对于确保对象的不可变性和类型安全非常有用。
下面是一个例子,演示了如何使用 Readonly
类型工具:
typescript
interface User {
readonly name: string;
readonly age: number;
readonly email: string;
}
function getUser(): Readonly<User> {
return { name: "John", age: 30, email: "john@example.com" };
}
const user: Readonly<User> = getUser();
console.log(user.name); // John
user.name = "John Doe"; // 无法修改只读属性,会报错
在上面的例子中,我们定义了一个 User
接口,它具有 name
、age
和 email
属性,但是这些属性都是只读的,即不能被修改。然后,我们定义了一个 getUser
函数,它返回一个 Readonly<User>
类型的只读用户对象。
通过使用 Readonly<User>
,我们可以确保用户对象在被赋值给变量 user
之后,其属性不能被修改。这有助于保证对象的不可变性和类型安全。
下面我们来看看它的实现:
typescript
/**
* Make all properties in T readonly
*/
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Readonly<T>
:通过type
关键字定义了一个泛型类型Readonly<T>
,其中T
是一个类型参数,表示待处理的类型。readonly [P in keyof T]: T[P]
:使用索引类型查询操作符keyof T
获取类型T
的所有属性,并使用in
关键字遍历这些属性。P
是遍历过程中的属性名,[P in keyof T]
表示在新类型中创建一个属性,属性名为P
。readonly
:在属性名前添加readonly
关键字,将属性的值设为只读。
综合起来,Readonly<T>
的作用是将类型 T
的所有属性转换为只读属性,即属性的值在赋值后不可修改。这个类型在实际开发中常用于对对象进行保护,防止意外的修改或者篡改属性值。
Pick
Pick
用于从给定类型中选择指定的属性,并创建一个新的类型。换句话说,Pick
可以从一个对象类型中挑选出指定的属性,创建一个新的类型,该类型只包含指定的属性。
使用 Pick
可以很方便地从一个复杂的类型中选择需要的部分,减少了不必要的冗余信息,提高了代码的可读性和灵活性。
下面是一个例子,演示了如何使用 Pick
类型工具:
typescript
interface User {
name: string;
age: number;
email: string;
address: string;
}
type UserBasicInfo = Pick<User, "name" | "age">;
const user: UserBasicInfo = {
name: "John",
age: 30,
};
在上面的例子中,我们定义了一个 User
接口,它具有 name
、age
、email
和 address
属性。然后,我们使用 Pick
类型工具创建了一个新的类型 UserBasicInfo
,它只包含了 name
和 age
属性。
通过使用 Pick<User, "name" | "age">
,我们从 User
类型中挑选出了 name
和 age
属性,创建了一个新的类型 UserBasicInfo
。然后,我们可以使用 UserBasicInfo
类型来定义 user
对象,该对象只包含了 name
和 age
属性。
下面我们来看看它的实现:
typescript
/**
* From T, pick a set of properties whose keys are in the union K
*/
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
type Pick<T, K extends keyof T>
:通过type
关键字定义了一个泛型类型Pick<T, K>
,其中T
是一个类型参数,表示待处理的类型,K
是一个类型参数,表示要选取的属性的键集合,K extends keyof T
表示K
必须是类型T
的键集合中的一部分。[P in K]: T[P]
:K
表示要选取的属性的键集合,使用in
关键字遍历这些属性。P
是遍历过程中的属性名,[P in K]
表示在新类型中创建一个属性,属性名为P
,并且只包含在K
中的属性。
综合起来,Pick<T, K>
的作用是从类型 T
中选取指定的属性,生成一个新的类型。这个类型在实际开发中常用于需要从一个大型类型中提取部分属性的情况,可以精确地选择需要的属性,避免了不必要的属性的引入。
Record
Record
用于创建一个具有指定属性类型的对象类型。Record
接受两个类型参数,第一个参数指定属性的名称,第二个参数指定属性的类型。
使用 Record
可以很方便地定义一个具有指定属性类型的对象类型,这对于创建字典、映射等数据结构非常有用。
下面是一个例子,演示了如何使用 Record
类型工具:
typescript
type Fruit = "apple" | "banana" | "orange";
type Price = number;
const fruitPrices: Record<Fruit, Price> = {
apple: 1.5,
banana: 0.5,
orange: 0.8,
};
console.log(fruitPrices.apple); // 1.5
console.log(fruitPrices.banana); // 0.5
console.log(fruitPrices.orange); // 0.8
在上面的例子中,我们定义了两个类型 Fruit
和 Price
,Fruit
是一个联合类型,表示水果的名称,Price
是一个数值类型,表示水果的价格。
然后,我们使用 Record<Fruit, Price>
创建了一个对象类型 fruitPrices
,该对象只能包含 Fruit
类型的属性,并且属性的值必须是 Price
类型。
通过使用 Record<Fruit, Price>
,我们创建了一个名为 fruitPrices
的对象,它包含了苹果、香蕉和橙子三个属性,并且它们的值分别对应了它们的价格。
下面我们来看看它的实现:
typescript
/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};
type Record<K extends keyof any, T>
:通过type
关键字定义了一个泛型类型Record<K, T>
,其中K
是一个类型参数,表示要作为属性键的类型,T
是一个类型参数,表示属性值的类型。K extends keyof any
表示K
必须是任意类型的键集合中的一部分。[P in K]: T
:使用索引类型查询操作符keyof any
获取任意类型的所有键,并使用in
关键字遍历这些键。P
是遍历过程中的键名,[P in K]
表示在新类型中创建一个属性,属性名为P
,属性值为类型T
。
综合起来,Record<K, T>
的作用是创建一个新类型,其中每个属性的键都是类型 K
中的元素,并且每个属性的值都是类型 T
。这个类型在实际开发中常用于需要创建具有特定键和值类型的对象的情况,可以方便地定义和操作这些对象。
Exclude
Exclude
用于从一个联合类型中排除指定的类型。
Exclude
接受两个类型参数,第一个参数是要排除的类型,第二个参数是要从中排除类型的联合类型。
下面是一个例子,演示了如何使用 Exclude
类型工具:
typescript
type Animal = "dog" | "cat" | "bird";
type ExcludeBird = Exclude<Animal, "bird">;
const myPets: ExcludeBird[] = ["dog", "cat"];
在上面的例子中,我们定义了一个联合类型 Animal
,它包含了三种动物类型:dog
、cat
和 bird
。
然后,我们使用 Exclude<Animal, "bird">
创建了一个新的类型 ExcludeBird
,该类型排除了 Animal
类型中的 bird
类型。
最后,我们定义了一个数组 myPets
,它的元素类型是 ExcludeBird
,即排除了 bird
类型的 Animal
类型。所以,myPets
数组只能包含 dog
和 cat
。
通过使用 Exclude
类型工具,我们可以方便地从一个联合类型中排除某个特定的类型,从而创建一个新的类型,以满足特定的需求。
下面我们来看看它的实现:
typescript
/**
* Exclude from T those types that are assignable to U
*/
type Exclude<T, U> = T extends U ? never : T;
type Exclude<T, U>
:通过type
关键字定义了一个泛型类型Exclude<T, U>
,其中T
是一个类型参数,表示待处理的类型,U
是一个类型参数,表示要排除的类型。T extends U ? never : T
:使用条件类型来判断类型T
是否可以赋值给类型U
。如果可以赋值,即T
是U
的子类型,那么返回never
类型,表示排除该类型。如果不可以赋值,即T
不是U
的子类型,那么返回T
类型本身。
综合起来,Exclude<T, U>
的作用是从类型 T
中排除所有可以赋值给类型 U
的类型,生成一个新的类型。这个类型在实际开发中常用于需要从一个类型中排除指定类型的情况,可以过滤掉不需要的类型,提高代码的类型安全性和灵活性。
Extract
Extract
用于从一个联合类型中提取指定的类型。
Extract
接受两个类型参数,第一个参数是要提取的类型,第二个参数是要从中提取类型的联合类型。
下面是一个例子,演示了如何使用 Extract
类型工具:
typescript
type Animal = "dog" | "cat" | "bird";
type ExtractBird = Extract<Animal, "bird">;
const myBird: ExtractBird = "bird";
在上面的例子中,我们定义了一个联合类型 Animal
,它包含了三种动物类型:dog
、cat
和 bird
。
然后,我们使用 Extract<Animal, "bird">
创建了一个新的类型 ExtractBird
,该类型提取了 Animal
类型中的 bird
类型。
最后,我们定义了一个变量 myBird
,它的类型是 ExtractBird
,即提取了 bird
类型的 Animal
类型。所以,myBird
只能是 bird
。
通过使用 Extract
类型工具,我们可以方便地从一个联合类型中提取某个特定的类型,以创建一个新的类型,以满足特定的需求。
下面我们来看看它的实现:
typescript
/**
* Extract from T those types that are assignable to U
*/
type Extract<T, U> = T extends U ? T : never;
type Extract<T, U>
:通过type
关键字定义了一个类型别名Extract<T, U>
,其中T
和U
是类型参数,分别表示待处理的类型和要提取的类型。T extends U ? T : never
:这是一个条件类型,它使用了类型的条件判断。如果类型T
可以赋值给类型U
,则返回类型T
本身,表示要提取该类型。如果类型T
不能赋值给类型U
,则返回never
类型,表示不提取该类型。
这个类型别名在实际开发中常用于需要仅保留特定类型的场景,可以根据类型关系对类型进行筛选和处理,提高代码的灵活性和类型安全性。
Omit
Omit
用于从一个对象类型中排除指定的属性。
Omit
接受两个类型参数,第一个参数是要从中排除属性的对象类型,第二个参数是要排除的属性的名称。
下面是一个例子,演示了如何使用 Omit
类型工具:
typescript
type Person = {
name: string;
age: number;
gender: string;
};
type OmitAge = Omit<Person, "age">;
const personWithoutAge: OmitAge = {
name: "John",
gender: "male"
};
在上面的例子中,我们定义了一个对象类型 Person
,它有三个属性:name
、age
和 gender
。
然后,我们使用 Omit<Person, "age">
创建了一个新的类型 OmitAge
,该类型排除了 Person
类型中的 age
属性。
最后,我们定义了一个变量 personWithoutAge
,它的类型是 OmitAge
,即排除了 age
属性的 Person
类型。所以,personWithoutAge
只包含 name
和 gender
属性。
通过使用 Omit
类型工具,我们可以方便地从一个对象类型中排除指定的属性,创建一个新的类型,以满足特定的需求。
下面我们来看看它的实现:
typescript
/**
* Construct a type with the properties of T except for those in type K.
*/
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
type Omit<T, K extends keyof any>
:通过type
关键字定义了一个类型别名Omit<T, K extends keyof any>
,其中T
和K
是类型参数,分别表示待处理的类型和要排除的属性。Pick<T, Exclude<keyof T, K>>
:这是一个使用了两个类型操作符的表达式。首先,keyof T
获取类型T
的所有属性名称组成的联合类型。然后,Exclude<keyof T, K>
从属性名称联合类型中排除掉类型K
中指定的属性。最后,Pick<T, Exclude<keyof T, K>>
从类型T
中选取排除指定属性后的属性来构建一个新的类型。
这个类型别名在实际开发中常用于需要从一个类型中删除特定属性的场景,可以灵活控制类型的结构和组合,提高代码的可复用性和可维护性。
NonNullable
NonNullable
用于从一个类型中排除 null
和 undefined
。
NonNullable
接受一个类型参数,该参数表示要排除 null
和 undefined
的类型。
下面是一个例子,演示了如何使用 NonNullable
类型工具:
typescript
type NullableString = string | null | undefined;
type NonNullableString = NonNullable<NullableString>;
const str: NonNullableString = "Hello";
在上面的例子中,我们定义了一个类型 NullableString
,它是一个包含 string
、null
和 undefined
的联合类型。
然后,我们使用 NonNullable<NullableString>
创建了一个新的类型 NonNullableString
,该类型排除了 NullableString
中的 null
和 undefined
。
最后,我们定义了一个变量 str
,它的类型是 NonNullableString
,即排除了 null
和 undefined
的 NullableString
类型。所以,str
只能是 string
类型。
通过使用 NonNullable
类型工具,我们可以方便地从一个类型中排除 null
和 undefined
,创建一个新的类型,以确保变量不会为 null
或 undefined
。
下面我们来看看它的实现:
typescript
/**
* Exclude null and undefined from T
*/
type NonNullable<T> = T & {};
type NonNullable<T>
:通过type
关键字定义了一个类型别名NonNullable<T>
,其中T
是类型参数,表示待处理的类型。T & {}
:这是一个交叉类型的表达式。交叉类型用于将多个类型合并为一个类型。在这里,T
和{}
(空对象字面量类型)进行交叉操作,表示将类型T
和空对象类型合并为一个新的类型。
这个类型别名在实际开发中常用于需要确保变量或属性不包含 null
或 undefined
的场景,可以提高代码的健壮性和类型安全性。
Parameters
Parameters<T>
是一个泛型工具类型,它用于获取函数类型 T
的参数类型。它接受一个函数类型作为参数,并返回一个元组类型,其中包含了函数的每个参数类型。
例如,假设有以下函数定义:
typescript
function greet(name: string, age: number): void {
console.log(`Hello, ${name}! You are ${age} years old.`);
}
可以使用Parameters
来获取greet
函数的参数类型:
typescript
type GreetParams = Parameters<typeof greet>;
// GreetParams 的类型为 [string, number]
在这个例子中,GreetParams
的类型被推断为一个元组类型,其中包含了greet
函数的两个参数的类型。
下面我们来看看它的实现:
typescript
/**
* Obtain the parameters of a function type in a tuple
*/
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
在 TypeScript 中,infer
是一个关键字,用于在条件类型中推断类型变量。条件类型是一种在类型系统中进行条件判断的方式,它可以根据不同的条件选择不同的类型。infer
关键字可以用于条件类型中的 extends
子句中,用于推断类型变量的具体类型。
在条件类型中,通常使用infer
关键字将类型变量绑定到待推断的类型上。这样,在使用条件类型时,可以通过infer
关键字来提取和操作这个类型。
在这个例子中,我们定义了一个Parameters<T>
条件类型,它接受一个函数类型T
作为参数。通过infer
关键字,我们将类型变量R
绑定到函数类型的参数上。如果T
是一个函数类型,那么Parameters<T>
将返回R
,即函数的参数类型;否则,返回never
。
infer
关键字的使用使得我们可以在条件类型中进行类型推断,从而更加灵活地操作和处理不同类型的情况。
ConstructorParameters
ConstructorParameters
用于获取构造函数的参数类型。
ConstructorParameters
接受一个构造函数类型作为参数,并返回一个元组类型,该元组类型包含了构造函数的参数类型。
下面是一个例子,演示了如何使用 ConstructorParameters
类型工具:
typescript
class Person {
constructor(name: string, age: number) {
// constructor implementation
}
}
type PersonConstructorParams = ConstructorParameters<typeof Person>;
const params: PersonConstructorParams = ["John", 25];
在上面的例子中,我们定义了一个 Person
类,它有一个构造函数,接受一个 name
参数和一个 age
参数。
然后,我们使用 ConstructorParameters<typeof Person>
创建了一个新的类型 PersonConstructorParams
,该类型是一个元组类型,包含了 Person
构造函数的参数类型。
最后,我们定义了一个变量 params
,它的类型是 PersonConstructorParams
,即 Person
构造函数的参数类型的元组。所以,params
是一个包含 name
和 age
的元组。
通过使用 ConstructorParameters
类型工具,我们可以方便地获取构造函数的参数类型,并将其用于声明变量、函数参数等。
下面我们来看看它的实现:
typescript
/**
* Obtain the parameters of a constructor function type in a tuple
*/
type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
type ConstructorParameters<T extends abstract new (...args: any) => any>
:通过type
关键字定义了一个类型别名ConstructorParameters<T extends abstract new (...args: any) => any>
,其中T
是类型参数,表示待处理的抽象构造函数类型。T extends abstract new (...args: infer P) => any ? P : never
:这是一个条件类型的表达式。条件类型用于根据某个条件选择不同的类型。在这里,T extends abstract new (...args: infer P) => any
是一个条件,如果T
是一个抽象构造函数类型,那么P
将被推断为构造函数的参数类型数组。而? P
表示当条件成立时,返回P
,即参数类型数组;而: never
表示当条件不成立时,返回never
类型。
这个类型别名在实际开发中常用于需要从抽象构造函数类型中获取构造函数参数类型的场景,可以用于构造函数的参数类型的推断和使用。
ReturnType
ReturnType<T>
是一个泛型工具类型,它用于获取函数类型T
的返回值类型。它接受一个函数类型作为参数,并返回该函数的返回值类型。
例如,假设有以下函数定义:
typescript
function add(a: number, b: number): number {
return a + b;
}
可以使用ReturnType
来获取add
函数的返回值类型:
typescript
type AddResult = ReturnType<typeof add>;
// AddResult 的类型为 number
在这个例子中,AddResult
的类型被推断为add
函数的返回值类型,即number
类型。
下面我们来看看它的实现:
typescript
/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
ReturnType<T>
条件类型,它接受一个函数类型T
作为参数。通过infer
关键字,我们将类型变量R
绑定到函数类型的返回值上。如果T是一个函数类型,那么ReturnType<T>
将返回R
,即函数的返回值类型;否则,返回never
。
InstanceType
InstanceType
用于获取构造函数的实例类型。
InstanceType
接受一个构造函数类型作为参数,并返回该构造函数类型的实例类型。
下面是一个例子,演示了如何使用 InstanceType
类型工具:
typescript
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}
type PersonInstance = InstanceType<typeof Person>;
const person: PersonInstance = new Person("John", 25);
person.sayHello();
在上面的例子中,我们定义了一个 Person
类,它有一个构造函数和一些实例方法。
然后,我们使用 InstanceType<typeof Person>
创建了一个新的类型 PersonInstance
,该类型是 Person
构造函数的实例类型。
最后,我们定义了一个变量 person
,它的类型是 PersonInstance
,即 Person
构造函数的实例类型。我们通过 new Person("John", 25)
创建了一个 Person
的实例,并将其赋值给 person
。
通过使用 InstanceType
类型工具,我们可以方便地获取构造函数的实例类型,并将其用于声明变量、函数返回值等。
下面我们来看看它的实现:
typescript
/**
* Obtain the return type of a constructor function type
*/
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
type InstanceType<T extends abstract new (...args: any) => any>
:通过type
关键字定义了一个类型别名InstanceType<T extends abstract new (...args: any) => any>
,其中T
是类型参数,表示待处理的抽象构造函数类型。T extends abstract new (...args: any) => infer R ? R : any
:这是一个条件类型的表达式。条件类型用于根据某个条件选择不同的类型。在这里,T extends abstract new (...args: any) => infer R
是一个条件,如果T
是一个抽象构造函数类型,那么R
将被推断为构造函数实例的类型。而? R
表示当条件成立时,返回R
,即构造函数实例的类型;而: any
表示当条件不成立时,返回any
类型。
这个类型别名在实际开发中常用于需要从抽象构造函数类型中获取构造函数实例类型的场景,可以用于构造函数实例类型的推断和使用。
Uppercase
Uppercase
用于将字符串类型的字母转换为大写。
Uppercase
接受一个字符串类型作为参数,并返回该字符串类型的大写版本。
下面是一个例子,演示了如何使用 Uppercase
类型工具:
typescript
type UppercaseString = Uppercase<"hello">;
// UppercaseString 的类型为 "HELLO"
const str: UppercaseString = "HELLO";
在上面的例子中,我们使用 Uppercase<"hello">
创建了一个新的类型 UppercaseString
,该类型是字符串类型 "hello"
的大写版本,即 "HELLO"
。
然后,我们定义了一个变量 str
,它的类型是 UppercaseString
,即字符串类型的大写版本。我们将字符串 "HELLO"
赋值给 str
。
通过使用 Uppercase
类型工具,我们可以方便地将字符串类型的字母转换为大写,并将其用于类型声明。
下面我们来看看它的实现:
typescript
/**
* Convert string literal type to uppercase
*/
type Uppercase<S extends string> = intrinsic;
type Uppercase<S extends string>
:通过type
关键字定义了一个类型别名Uppercase<S extends string>
,其中S
是类型参数,表示待处理的字符串类型。intrinsic
:这是一个占位符,表示实际的内置类型或函数。在这里,intrinsic
代表了一个内部实现,用于将字符串类型中的字符转换为大写形式。
综合起来,Uppercase<S>
的作用是将字符串类型 S
中的字符转换为大写形式,并返回一个新的类型。
需要注意的是,这段代码中的 intrinsic
只是为了表示一个内部实现的占位符,并不是实际的代码。在实际开发中,我们可以使用 TypeScript 提供的内置类型 Uppercase<S>
来实现将字符串类型中的字符转换为大写形式的功能。
Lowercase
Lowercase
用于将字符串类型的字母转换为小写。
Lowercase
接受一个字符串类型作为参数,并返回该字符串类型的小写版本。
下面是一个例子,演示了如何使用 Lowercase
类型工具:
typescript
type LowercaseString = Lowercase<"HELLO">;
// LowercaseString 的类型为 "hello"
const str: LowercaseString = "hello";
在上面的例子中,我们使用 Lowercase<"HELLO">
创建了一个新的类型 LowercaseString
,该类型是字符串类型 "HELLO"
的小写版本,即 "hello"
。
然后,我们定义了一个变量 str
,它的类型是 LowercaseString
,即字符串类型的小写版本。我们将字符串 "hello"
赋值给 str
。
通过使用 Lowercase
类型工具,我们可以方便地将字符串类型的字母转换为小写,并将其用于类型声明。
下面我们来看看它的实现:
typescript
/**
* Convert string literal type to lowercase
*/
type Lowercase<S extends string> = intrinsic;
type Lowercase<S extends string>
:通过type
关键字定义了一个类型别名Lowercase<S extends string>
,其中S
是类型参数,表示待处理的字符串类型。intrinsic
:这是一个占位符,表示实际的内置类型或函数。在这里,intrinsic
代表了一个内部实现,用于将字符串类型中的字符转换为小写形式。
需要注意的是,这段代码中的 intrinsic
只是为了表示一个内部实现的占位符,并不是实际的代码。在实际开发中,我们可以使用 TypeScript 提供的内置类型 Lowercase<S>
来实现将字符串类型中的字符转换为小写形式的功能。
Capitalize
Capitalize
用于将字符串的第一个字符转换为大写。
例如:
typescript
type MyString = 'hello';
type CapitalizedString = Capitalize<MyString>;
// CapitalizedString 的类型为 'Hello'
在上面的例子中,我们使用 Capitalize
类型工具将字符串类型 MyString
的第一个字符转换为大写,并将结果赋值给类型别名 CapitalizedString
。由于 MyString
的值是 'hello'
,所以 CapitalizedString
的类型为 'Hello'
。
需要注意的是,Capitalize
只能应用于字符串类型。如果尝试将其他类型(如数字、布尔值)应用于 Capitalize
,则会得到一个编译时错误。
下面我们来看看它的实现:
typescript
/**
* Convert first character of string literal type to uppercase
*/
type Capitalize<S extends string> = intrinsic;
Uncapitalize
Uncapitalize
用于将字符串的第一个字符转换为小写。
例如:
typescript
type MyString = 'Hello';
type UncapitalizedString = Uncapitalize<MyString>;
// UncapitalizedString 的类型为 'hello'
在上面的例子中,我们使用 Uncapitalize
类型工具将字符串类型 MyString
的第一个字符转换为小写,并将结果赋值给类型别名 UncapitalizedString
。由于 MyString
的值是 'Hello'
,所以 UncapitalizedString
的类型为 'hello'
。
需要注意的是,Uncapitalize
只能应用于字符串类型。如果尝试将其他类型(如数字、布尔值)应用于 Uncapitalize
,则会得到一个编译时错误。
下面我们来看看它的实现:
typescript
/**
* Convert first character of string literal type to lowercase
*/
type Uncapitalize<S extends string> = intrinsic;