盘点 TypeScript 内置类型
盘点 TypeScript 内置类型
- 盘点 TypeScript 内置类型
- Partial
- Required
- Readonly
- Pick
- Record
- Exclude
- Extract
- Omit
- NonNullable
- Parameters
- ConstructorParameters
- ReturnType
- InstanceType
- Uppercase
- Lowercase
- Capitalize
- Uncapitalize
盘点 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
类型工具:
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 中的一个有用工具,它可以帮助我们定义具有可选属性的对象类型,并在需要时方便地更新对象的部分属性。
下面我们来看看它的实现:
/*** 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
类型工具:
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
对象,而不能省略任何必需的属性。这有助于保证创建的用户对象具有所需的完整性和类型安全。
下面我们来看看它的实现:
/*** 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
类型工具:
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
之后,其属性不能被修改。这有助于保证对象的不可变性和类型安全。
下面我们来看看它的实现:
/*** 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
类型工具:
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
属性。
下面我们来看看它的实现:
/*** 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
类型工具:
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
的对象,它包含了苹果、香蕉和橙子三个属性,并且它们的值分别对应了它们的价格。
下面我们来看看它的实现:
/*** 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
类型工具:
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
类型工具,我们可以方便地从一个联合类型中排除某个特定的类型,从而创建一个新的类型,以满足特定的需求。
下面我们来看看它的实现:
/*** 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
类型工具:
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
类型工具,我们可以方便地从一个联合类型中提取某个特定的类型,以创建一个新的类型,以满足特定的需求。
下面我们来看看它的实现:
/*** 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
类型工具:
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
类型工具,我们可以方便地从一个对象类型中排除指定的属性,创建一个新的类型,以满足特定的需求。
下面我们来看看它的实现:
/*** 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
类型工具:
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
。
下面我们来看看它的实现:
/*** 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
的参数类型。它接受一个函数类型作为参数,并返回一个元组类型,其中包含了函数的每个参数类型。
例如,假设有以下函数定义:
function greet(name: string, age: number): void {console.log(`Hello, ${name}! You are ${age} years old.`);
}
可以使用Parameters
来获取greet
函数的参数类型:
type GreetParams = Parameters<typeof greet>;
// GreetParams 的类型为 [string, number]
在这个例子中,GreetParams
的类型被推断为一个元组类型,其中包含了greet
函数的两个参数的类型。
下面我们来看看它的实现:
/*** 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
类型工具:
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
类型工具,我们可以方便地获取构造函数的参数类型,并将其用于声明变量、函数参数等。
下面我们来看看它的实现:
/*** 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
的返回值类型。它接受一个函数类型作为参数,并返回该函数的返回值类型。
例如,假设有以下函数定义:
function add(a: number, b: number): number {return a + b;
}
可以使用ReturnType
来获取add
函数的返回值类型:
type AddResult = ReturnType<typeof add>;
// AddResult 的类型为 number
在这个例子中,AddResult
的类型被推断为add
函数的返回值类型,即number
类型。
下面我们来看看它的实现:
/*** 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
类型工具:
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
类型工具,我们可以方便地获取构造函数的实例类型,并将其用于声明变量、函数返回值等。
下面我们来看看它的实现:
/*** 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
类型工具:
type UppercaseString = Uppercase<"hello">;
// UppercaseString 的类型为 "HELLO"const str: UppercaseString = "HELLO";
在上面的例子中,我们使用 Uppercase<"hello">
创建了一个新的类型 UppercaseString
,该类型是字符串类型 "hello"
的大写版本,即 "HELLO"
。
然后,我们定义了一个变量 str
,它的类型是 UppercaseString
,即字符串类型的大写版本。我们将字符串 "HELLO"
赋值给 str
。
通过使用 Uppercase
类型工具,我们可以方便地将字符串类型的字母转换为大写,并将其用于类型声明。
下面我们来看看它的实现:
/*** 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
类型工具:
type LowercaseString = Lowercase<"HELLO">;
// LowercaseString 的类型为 "hello"const str: LowercaseString = "hello";
在上面的例子中,我们使用 Lowercase<"HELLO">
创建了一个新的类型 LowercaseString
,该类型是字符串类型 "HELLO"
的小写版本,即 "hello"
。
然后,我们定义了一个变量 str
,它的类型是 LowercaseString
,即字符串类型的小写版本。我们将字符串 "hello"
赋值给 str
。
通过使用 Lowercase
类型工具,我们可以方便地将字符串类型的字母转换为小写,并将其用于类型声明。
下面我们来看看它的实现:
/*** 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
用于将字符串的第一个字符转换为大写。
例如:
type MyString = 'hello';
type CapitalizedString = Capitalize<MyString>;
// CapitalizedString 的类型为 'Hello'
在上面的例子中,我们使用 Capitalize
类型工具将字符串类型 MyString
的第一个字符转换为大写,并将结果赋值给类型别名 CapitalizedString
。由于 MyString
的值是 'hello'
,所以 CapitalizedString
的类型为 'Hello'
。
需要注意的是,Capitalize
只能应用于字符串类型。如果尝试将其他类型(如数字、布尔值)应用于 Capitalize
,则会得到一个编译时错误。
下面我们来看看它的实现:
/*** Convert first character of string literal type to uppercase*/
type Capitalize<S extends string> = intrinsic;
Uncapitalize
Uncapitalize
用于将字符串的第一个字符转换为小写。
例如:
type MyString = 'Hello';
type UncapitalizedString = Uncapitalize<MyString>;
// UncapitalizedString 的类型为 'hello'
在上面的例子中,我们使用 Uncapitalize
类型工具将字符串类型 MyString
的第一个字符转换为小写,并将结果赋值给类型别名 UncapitalizedString
。由于 MyString
的值是 'Hello'
,所以 UncapitalizedString
的类型为 'hello'
。
需要注意的是,Uncapitalize
只能应用于字符串类型。如果尝试将其他类型(如数字、布尔值)应用于 Uncapitalize
,则会得到一个编译时错误。
下面我们来看看它的实现:
/*** Convert first character of string literal type to lowercase*/
type Uncapitalize<S extends string> = intrinsic;
相关文章:

盘点 TypeScript 内置类型
盘点 TypeScript 内置类型 盘点 TypeScript 内置类型PartialRequiredReadonlyPickRecordExcludeExtractOmitNonNullableParametersConstructorParametersReturnTypeInstanceTypeUppercaseLowercaseCapitalizeUncapitalize 盘点 TypeScript 内置类型 当开发者开始学习 TypeScri…...

Netty 执行了多次channelReadComplete()却没有执行ChannelRead()
[TOC](Netty 执行了多次channelReadComplete()) Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive. happy for hardess to solve denpendies.…...

直线导轨的精密等级以及划分依据
直线导轨的作用,是用来支撑和引导运动部件,按给定的方向做往复直线运动的,直线导轨是高精密度的传动元件,广泛使用在各行各业中。 直线导轨的精密等级是判断产品质量的一个重要指标。在众多种类的直线导轨产品中,精密等…...

Ubuntu Server版 之 apache系列 常用配置 以及 隐藏 版本号 IP、Port 搭建服务案例
查看版本 旧的 用 httpd -v 新的 用 apache2 -v 配置检测 旧的 httpd -t 新的 apachectl configtest window用的apache 是 httpd -t Linux 中 apachectl configtest 主配置文件 之前旧版apache 是httpd 现在都改成 apache2 /etc/apache2/apache2.conf window中 httpd.con…...

Kubernetes(K8s)从入门到精通系列之七:K8s的基本概念和术语之安全类
Kubernetes K8s从入门到精通系列之七:K8s的基本概念和术语之安全类 一、安全类二、Role和ClusterRole三、RoleBinding和ClusterRoleBinding一、安全类 开发的Pod应用需要通过API Server查询、创建及管理其他相关资源对象,所以这类用户才是K8s的关键用户。K8s设计了Service A…...

网络安全(黑客)自学误区
前言 网络安全是当今社会中至关重要的议题。随着科技的迅猛发展,网络已经渗透到我们生活的方方面面,给我们带来了巨大的便利和机遇。然而,网络也存在着各种风险和威胁,如黑客攻击、数据泄露等。因此,学习网络安全知识…...

在OK3588板卡上部署模型实现人工智能OCR应用
一、主机模型转换 我们依旧采用FastDeploy来部署应用深度学习模型到OK3588板卡上 进入主机Ubuntu的虚拟环境 conda activate ok3588 安装rknn-toolkit2(该工具不能在OK3588板卡上完成模型转换) git clone https://github.com/rockchip-linux/rknn-to…...

在linux中怎样同时运行三个微服务保证退出时不会终止
前言 1.maven中打jar包 使用插件打包,必须在pom.xml中添加插件,否则不能在linux中编译运行 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version&g…...

MD-MTSP:成长优化算法GO求解多仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)
一、成长优化算法GO 成长优化算法(Growth Optimizer,GO)由Qingke Zhang等人于2023年提出,该算法的设计灵感来源于个人在成长过程中的学习和反思机制。学习是个人通过从外部世界获取知识而成长的过程,反思是检查个体自…...

Python入门一
目录: python基本操作python基本数据类型python字符串基本操作python的运算符python控制流-判断python控制流-循环python常用数据结构-列表python常用数据结构-元组python常用数据结构-集合python常用数据结构-字典python函数python函数进阶与参数处理pythonlambda…...

mysql_2.4——安装常见问题
1. 将MySQL添加到环境变量 将 mysql 的 bin 目录地址添加到 系统环境变量 --> PATH 中 2. 将MySQL添加到服务 以管理员的方式启动 cmd (命令提示窗口),使用命令进入到 [mysql]\bin ,执行如下命 令。 # mysqld --install (服务名) # 如: mysqld --…...

行业追踪,2023-07-31,板块多数都是指向消费
自动复盘 2023-07-31 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...

K8S故障排查
故障现象:部署pod时,报错没发调度到节点。 排查步骤: 1、查看集群的状态 [rootk8s-master1 nginx]#kubectl get nodes2、查看k8s组件的状态-kubelet,kube-apiservice 3、查看docker的Cgroup driver和k8s的Cgroup driver类型&…...

idea集成jrebel实现热部署
文章目录 idea集成jrebel实现热部署下载jrebel 插件包下载jrebel mybatisplus extensition 插件包基础配置信息情况一其次情况三情况四情况五情况六情况七 验证生效与否 Jrebel热部署不生效的解决办法 idea集成jrebel实现热部署 在平常开发项目中,我们通常是修改完…...

【Git系列】Git配置SSH免密登录
🐳Git配置SSH免密登录 🧊1.设置用户名和邮箱🧊2. 生成密钥🧊3.远程仓库配置密钥🧊2. 免密登录 在以上push操作过程中,我们第一次push时,是需要进行录入用户名和密码的,比较麻烦。而且…...

Node.js 安装与版本管理(nvm 的使用)
安装 Node.js Node.js 诞生于 2009 年 5 月,截至今天(2022 年 3 月 26 号)的最新版本为 16.14.2 LTS 和 17.8.0 Current,可以去官网下载合适的版本。 其中,LTS(Long Term Support) 是长期维护…...

SpringBoot项目中使用Lombok插件中Slf4j日志框架
前言:idea需要安装lombok插件,因为该插件中添加了Slf4j注解,可以将Slf4j翻译成 private static final org.slf4j.Logger logger LoggerFactory.getLogger(this.XXX.class); springboot本身就内置了slf4j日志框架,所以不需要单独…...

VS下开发Qt应用环境搭建
VS下开发Qt应用环境搭建 版本说明环境搭建步骤QT新增组件重新安装QTVS中的配置 版本说明 vs2019 QT5.14 我之前是按照QT基础组件的安装,但是这个安装只是最基础的组件,如果想要在VS中使用QT,还得安装其他组件,下面的安装流程、 …...

Python实现GA遗传算法优化循环神经网络分类模型(LSTM分类算法)项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法(Genetic Algorithm,GA)最早是由美国的 John holland于20世…...

Spring源码:Spring运行环境Environment
Spring运行环境 Spring在创建容器时,会创建Environment环境对象,用于保存spring应用程序的运行环境相关的信息。在创建环境时,需要创建属性源属性解析器,会解析属性值中的占位符,并进行替换。 创建环境时,…...

SpringBoot使用PropertiesLauncher加载外部jar包
Springboot启动入口源码 默认是org.springframework.boot.loader.JarLauncher <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-loader</artifactId> </dependency>启用SpringBoot的PropertiesLaunche…...

骑行 - 出发前如何准备
现在路上经常见到武装完备的自行车骑手,一般是公路车,出来骑个几十公里是很正常的。出来骑车是个很快乐的事,但出发前还是有许多需要准备的。 最开始,要评估一下天气情况,出车前看下外面天气情况以及预报。提前几天计划…...

ssm员工管理系统
ssm员工管理系统 java员工管理系统 员工管理系统 运行环境: JAVA版本:JDK1.8 IDE类型:IDEA、Eclipse都可运行 数据库类型:MySql(8.x版本都可) 硬件环境:Windows 功能介绍: 1.用户…...

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(16)-Fiddler如何充当第三者再识AutoResponder标签-上
1.简介 Fiddler充当第三者,主要是通过AutoResponder标签在客户端和服务端之间,Fiddler抓包,然后改包,最后发送。AutoResponder这个功能可以算的上是Fiddler最实用的功能,可以让我们修改服务器端返回的数据,…...

Yolov8新版本解读:优化点如何加入新版本,通过加入EMA注意力进行对比说明
本文目的: 最近yolov8进行了一次较大的更新,对一些优化点加在哪个位置上有些变动,因此本文主要通过具体案列进行对比和说明,以便在新版本上能够轻松上手。 老版本 ultralytics/nn 新版本更新为: modules文件夹下内容如下: 解读: 将modules.py拆分为 1.__init__.…...

NoSQL———Redis配置与优化
目录 一、关系数据库与非关系型数据库 1.1 关系型数据库 1.2 非关系型数据库 1.3 关系型数据库和非关系型数据库区别 1.3.1 非关系型数据库产生背景 二、Redis简介 2.1 redis优点: 三、Redis 安装部署 四、Redis 命令工具 4.1 redis-cli 命令行工具 …...

js,瀑布流
该方法仅满足,元素等宽,高度一般不同的瀑布流布局 计算元素宽度与浏览器宽度之比,得到布局列数;将未布局的元素依次布局至高度最小的那一列;页面滚动时继续加载数据,动态地渲染在页面上。 <div id&quo…...

“深入了解Spring Boot:从入门到精通“
标题:深入了解Spring Boot:从入门到精通 摘要:本文将介绍Spring Boot的基本概念、特性和优势,以及如何使用Spring Boot来开发Java应用程序。通过深入学习Spring Boot的核心组件和常用功能,读者将能够熟练运用Spring B…...

记录时间计算bug getDay()的一个坑
最近在使用时间计算展示当天所在这一周的数据 不免要获取当前时间所在周 // 时间格式整理函数 function formatDate(date) {const year date.value.getFullYear(),month String(date.value.getMonth() 1).padStart(2, 0),day String(date.value.getDate()).padStart(2, 0)…...

【lesson5】linux vim介绍及使用
文章目录 vim的基本介绍vim的基本操作vim常见的命令命令模式下的命令yypnyynpuctrlrGggnG$^wbh,j,k,lddnddnddp~shiftrrnrxnx 底行模式下的命令set nuset nonuvs 源文件wq!command(命令) vim配置解决无法使用sudo问题 vim的基本介绍 首先vim是linux下的…...