没有网站百度推广吗网站建设考试试题
- 作者: 五速梦信息网
- 时间: 2026年04月20日 10:27
当前位置: 首页 > news >正文
没有网站百度推广吗,网站建设考试试题,wordpress 发通知,什么是软件外包公司一、泛型是什么#xff1f;有什么作用#xff1f;
当我们定义一个变量不确定类型的时候有两种解决方式#xff1a; 使用any 使用any定义时存在的问题#xff1a;虽然知道传入值的类型但是无法获取函数返回值的类型#xff1b;另外也失去了ts类型保护的优势 使用泛型 泛型…一、泛型是什么有什么作用
当我们定义一个变量不确定类型的时候有两种解决方式 使用any 使用any定义时存在的问题虽然知道传入值的类型但是无法获取函数返回值的类型另外也失去了ts类型保护的优势 使用泛型 泛型指的是在定义函数/接口/类型时不预先指定具体的类型而是在使用的时候在指定类型限制的一种特性。 设计泛型的关键目的是在成员之间提供有意义的约束这些成员可以是类的实例成员、类的方法、函数参数和函数返回值。
为了便于大家更好地理解上述的内容我们来举个例子在这个例子中我们将一步步揭示泛型的作用。首先我们来定义一个通用的 identity 函数该函数接收一个参数并直接返回它
function identity (value) {return value;
}console.log(identity(1)) // 1现在我们将 identity 函数做适当的调整以支持 TypeScript 的 Number 类型的参数
function identity (value: Number) : Number {return value;
}console.log(identity(1)) // 1这里 identity 的问题是我们将 Number 类型分配给参数和返回类型使该函数仅可用于该原始类型。但该函数并不是可扩展或通用的很明显这并不是我们所希望的。
我们确实可以把 Number 换成 any我们失去了定义应该返回哪种类型的能力并且在这个过程中使编译器失去了类型保护的作用。我们的目标是让 identity 函数可以适用于任何特定的类型为了实现这个目标我们可以使用泛型来解决这个问题具体实现方式如下
function identity T(value: T) : T {return value;
}console.log(identityNumber(1)) // 1对于刚接触 TypeScript 泛型的读者来说首次看到 语法会感到陌生。但这没什么可担心的就像传递参数一样我们传递了我们想要用于特定函数调用的类型。 参考上面的图片当我们调用 identity(1) Number 类型就像参数 1 一样它将在出现 T 的任何位置填充该类型。图中 T 内部的 T 被称为类型变量它是我们希望传递给 identity 函数的类型占位符同时它被分配给 value 参数用来代替它的类型此时 T 充当的是类型而不是特定的 Number 类型。
其中 T 代表 Type在定义泛型时通常用作第一个类型变量名称。但实际上 T 可以用任何有效名称代替。除了 T 之外以下是常见泛型变量代表的意思
KKey表示对象中的键类型VValue表示对象中的值类型EElement表示元素类型
其实并不是只能定义一个类型变量我们可以引入希望定义的任何数量的类型变量。比如我们引入一个新的类型变量 U用于扩展我们定义的 identity 函数
function identity T, U(value: T, message: U) : T {console.log(message);return value;
}console.log(identityNumber, string(68, Semlinker));除了为类型变量显式设定值之外一种更常见的做法是使编译器自动选择这些类型从而使代码更简洁。我们可以完全省略尖括号比如
function identity T, U(value: T, message: U) : T {console.log(message);return value;
}console.log(identity(68, Semlinker));如你所见该函数接收你传递给它的任何类型使得我们可以为不同类型创建可重用的组件。现在我们再来看一下 identity 函数
function identity T, U(value: T, message: U) : T {console.log(message);return value;
}相比之前定义的 identity 函数新的 identity 函数增加了一个类型变量 U但该函数的返回类型我们仍然使用 T。如果我们想要返回两种类型的对象该怎么办呢针对这个问题我们有多种方案其中一种就是使用元组即为元组设置通用的类型
function identity T, U(value: T, message: U) : [T, U] {return [value, message];
}虽然使用元组解决了上述的问题但有没有其它更好的方案呢答案是有的你可以使用泛型接口。
二、泛型用法
1、在函数中使用泛型
function test T (arg:T):T{console.log(arg);return arg;
}
testnumber(111);// 返回值是number类型的 111
teststring | boolean(hahaha)//返回值是string类型的 hahaha
teststring | boolean(true);//返回值是布尔类型的 true// 使用方式类似于函数传参传什么数据类型T就表示什么数据类型 使用表示T也可以换成任意字符串。2、在接口中使用泛型
// 注意这里写法是定义的方法
interface Search {T,Y(name:T,age:Y):T
}let fn:Search function T, Y(name: T, id:Y):T {console.log(name, id)return name;
}
fn(li,11);//编译器会自动识别传入的参数将传入的参数的类型认为是泛型指定的类型
为了解决刚刚上面提到的问题首先让我们创建一个用于的 identity 函数通用 Identities 接口
interface IdentitiesV, M {value: V,message: M
}在上述的 Identities 接口中我们引入了类型变量 V 和 M来进一步说明有效的字母都可以用于表示类型变量之后我们就可以将 Identities 接口作为 identity 函数的返回类型
function identityT, U (value: T, message: U): IdentitiesT, U {console.log(value : typeof (value));console.log(message : typeof (message));let identities: IdentitiesT, U {value,message};return identities;
}console.log(identity(68, Semlinker));以上代码成功运行后在控制台会输出以下结果
68: number
Semlinker: string
{value: 68, message: Semlinker}泛型除了可以应用在函数和接口之外它也可以应用在类中下面我们就来看一下在类中如何使用泛型。
3、在类中使用泛型
class AnimalT {name:T;constructor(name: T){this.name name;}actionT(say:T) {console.log(say)}
}
let cat new Animal(cat);
cat.action(mimi)在类中使用泛型也很简单我们只需要在类名后面使用 T, … 的语法定义任意多个类型变量具体示例如下
interface GenericInterfaceU {value: UgetIdentity: () U
}class IdentityClassT implements GenericInterfaceT {value: Tconstructor(value: T) {this.value value}getIdentity(): T {return this.value}}const myNumberClass new IdentityClassNumber(68);
console.log(myNumberClass.getIdentity()); // 68const myStringClass new IdentityClassstring(Semlinker!);
console.log(myStringClass.getIdentity()); // Semlinker!接下来我们以实例化 myNumberClass 为例来分析一下其调用过程
在实例化 IdentityClass 对象时我们传入 Number 类型和构造函数参数值 68之后在 IdentityClass 类中类型变量 T 的值变成 Number 类型IdentityClass 类实现了 GenericInterface T 而此时 T 表示 Number 类型因此等价于该类实现了 GenericInterface Number 接口而对于 GenericInterface T 接口来说类型变量 U 也变成了 Number。这里我有意使用不同的变量名以表明类型值沿链向上传播且与变量名无关。泛型类可确保在整个类中一致地使用指定的数据类型。比如你可能已经注意到在使用 Typescript 的 React 项目中使用了以下约定
type Props {className?: string…
};type State {submitted?: bool…
};class MyComponent extends React.ComponentProps, State {…
}在以上代码中我们将泛型与 React 组件一起使用以确保组件的 props 和 state 是类型安全的。
相信看到这里一些读者会有疑问我们在什么时候需要使用泛型呢通常在决定是否使用泛型时我们有以下两个参考标准
当你的函数、接口或类将处理多种数据类型时当函数、接口或类在多个地方使用该数据类型时。
很有可能你没有办法保证在项目早期就使用泛型的组件但是随着项目的发展组件的功能通常会被扩展。这种增加的可扩展性最终很可能会满足上述两个条件在这种情况下引入泛型将比复制组件来满足一系列数据类型更干净。
我们将在本文的后面探讨更多满足这两个条件的用例。不过在这样做之前让我们先介绍一下 Typescript 泛型提供的其他功能。
三、泛型约束
interface Person {name:string;age:number;
}
function studentT extends Person(arg:T):T {return arg;
}student({name:lili});//类型 { name: string; } 中缺少属性 age但类型 Person 中需要该属性
student({ name: lili , age:11});//不能将类型“string”分配给类型“number”
student({ name: lili , age:11});有时我们可能希望限制每个类型变量接受的类型数量这就是泛型约束的作用。下面我们来举几个例子介绍一下如何使用泛型约束。
1、确保属性存在
一个很好的例子是在处理字符串或数组时我们会假设 length 属性是可用的。让我们再次使用 identity 函数并尝试输出参数的长度
function identityT(arg: T): T {console.log(arg.length); // Errorreturn arg;
}在这种情况下编译器将不会知道 T 确实含有 length 属性尤其是在可以将任何类型赋给类型变量 T 的情况下。我们需要做的就是让类型变量 extends 一个含有我们所需属性的接口比如这样
interface Length {length: number;
}function identityT extends Length(arg: T): T {console.log(arg.length); // 可以获取length属性return arg;
}T extends Length 用于告诉编译器我们支持已经实现 Length 接口的任何类型。之后当我们使用不含有 length 属性的对象作为参数调用 identity 函数时TypeScript 会提示相关的错误信息
identity(68); // Error
// Argument of type 68 is not assignable to parameter of type Length.(2345)此外我们还可以使用 , 号来分隔多种约束类型比如T extends Length, Type2, Type3。而对于上述的 length 属性问题来说如果我们显式地将变量设置为数组类型也可以解决该问题具体方式如下
function identityT(arg: T[]): T[] {console.log(arg.length); return arg;
}// or
function identityT(arg: ArrayT): ArrayT { console.log(arg.length);return arg;
}2、检查对象上的键是否存在
泛型约束的另一个常见的使用场景就是检查对象上的键是否存在。不过在看具体示例之前我们得来了解一下 keyof 操作符keyof 操作符是在 TypeScript 2.1 版本引入的该操作符可以用于获取某种类型的所有键其返回类型是联合类型。 “耳听为虚眼见为实”我们来举个 keyof 的使用示例
interface Person {name: string;age: number;location: string;
}type K1 keyof Person; // name | age | location
type K2 keyof Person[]; // number | length | push | concat | …
type K3 keyof { [x: string]: Person }; // string | number通过 keyof 操作符我们就可以获取指定类型的所有键之后我们就可以结合前面介绍的 extends 约束即限制输入的属性名包含在 keyof 返回的联合类型中。具体的使用方式如下
function getPropertyT, K extends keyof T(obj: T, key: K): T[K] {return obj[key];
}在以上的 getProperty 函数中我们通过 K extends keyof T 确保参数 key 一定是对象中含有的键这样就不会发生运行时错误。这是一个类型安全的解决方案与简单调用 let value obj[key]; 不同。
下面我们来看一下如何使用 getProperty 函数
enum Difficulty {Easy,Intermediate,Hard
}function getPropertyT, K extends keyof T(obj: T, key: K): T[K] {return obj[key];
}let tsInfo {name: Typescript,supersetOf: Javascript,difficulty: Difficulty.Intermediate
}let difficulty: Difficulty getProperty(tsInfo, difficulty); // OKlet supersetOf: string getProperty(tsInfo, superset_of); // Error在以上示例中对于 getProperty(tsInfo, ‘superset_of’) 这个表达式TypeScript 编译器会提示以下错误信息
Argument of type superset_of is not assignable to parameter of type
difficulty | name | supersetOf.(2345)很明显通过使用泛型约束在编译阶段我们就可以提前发现错误大大提高了程序的健壮性和稳定性。接下来我们来介绍一下泛型参数默认类型。
3、数组泛型
let arr:Arraynumber [1,2,3] let arr:number[][1,2,3]四、泛型参数默认类型
在 TypeScript 2.3 以后我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数从实际值参数中也无法推断出类型时这个默认类型就会起作用。
泛型参数默认类型与普通函数默认值类似对应的语法很简单即 TDefault Type对应的使用示例如下
interface ATstring {name: T;
}const strA: A { name: Semlinker };
const numB: Anumber { name: 101 };泛型参数的默认类型遵循以下规则
有默认类型的类型参数被认为是可选的。必选的类型参数不能在可选的类型参数后。如果类型参数有约束类型参数的默认类型必须满足这个约束。当指定类型实参时你只需要指定必选类型参数的类型实参。 未指定的类型参数会被解析为它们的默认类型。如果指定了默认类型且类型推断无法选择一个候选类型那么将使用默认类型作为推断结果。一个被现有类或接口合并的类或者接口的声明可以为现有类型参数引入默认类型。一个被现有类或接口合并的类或者接口的声明可以引入新的类型参数只要它指定了默认类型。
五、泛型条件类型
在 TypeScript 2.8 中引入了条件类型使得我们可以根据某些条件得到不同的类型这里所说的条件是类型兼容性约束。尽管以上代码中使用了 extends 关键字也不一定要强制满足继承关系而是检查是否满足结构兼容性。
条件类型会以一个条件表达式进行类型关系检测从而在两种类型中选择其一
T extends U ? X : Y以上表达式的意思是若 T 能够赋值给 U那么类型是 X否则为 Y。在条件类型表达式中我们通常还会结合 infer 关键字实现类型抽取
interface DictionaryT any {[key: string]: T;
}type StrDict Dictionarystringtype DictMemberT T extends Dictionaryinfer V ? V : never
type StrDictMember DictMemberStrDict // string在上面示例中当类型 T 满足 T extends Dictionary 约束时我们会使用 infer 关键字声明了一个类型变量 V并返回该类型否则返回 never 类型。
在 TypeScript 中never 类型表示的是那些永不存在的值的类型。 例如 never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。另外需要注意的是没有类型是 never 的子类型或可以赋值给 never 类型除了 never 本身之外。 即使 any 也不可以赋值给 never。
除了上述的应用外利用条件类型和 infer 关键字我们还可以方便地实现获取 Promise 对象的返回值类型比如
async function stringPromise() {return Hello, Semlinker!;
}interface Person {name: string;age: number;
}async function personPromise() {return { name: Semlinker, age: 30 } as Person;
}type PromiseTypeT (args: any[]) PromiseT;
type UnPromisifyT T extends PromiseTypeinfer U ? U : never;type extractStringPromise UnPromisifytypeof stringPromise; // string
type extractPersonPromise UnPromisifytypeof personPromise; // Person
六、泛型工具类型
1、Partial
partial T 的作用就是将某个类型中的属性全部变为可选项?
interface Person {name:string;age:number;
}
function studentT extends Person(arg: PartialT):PartialT {return arg;
}interface Todo {title: string;description: string;
}function updateTodo(todo: Todo, fieldsToUpdate: PartialTodo) {return { …todo, …fieldsToUpdate };
}const todo1 {title: organize desk,description: clear clutter
};const todo2 updateTodo(todo1, {description: throw out trash
});在上面的 updateTodo 方法中我们利用 Partial T 工具类型定义 fieldsToUpdate 的类型为 Partial Todo 即
{title?: string | undefined;description?: string | undefined;
}2、Record
RecordK extends keyof any, T 的作用是将 K 中所有的属性的值转化为 T 类型。
interface PageInfo {title: string
}
type Page home|about|other;
const x: RecordPage, PageInfo {home: { title: xxx },about: { title: aaa },other: { title: ccc },
};3、Pick
PickT, K extends keyof T的作用是将某个类型中的子属性挑出来变成包含这个类型部分属性的子类型示例
interface Todo {title:string,desc:string,time:string
}
type TodoPreview PickTodo, title|time;
const todo: TodoPreview {title:吃饭,time:明天
}4、Exclude
ExcludeT,U的作用是将某个类型中属于另一个类型的属性移除掉示例
type T0 Excludea | b | c, a; // b | c
const t:T0 b;type T0 Excludea | b | c, a; // b | c
type T1 Excludea | b | c, a | b; // c
type T2 Excludestring | number | (() void), Function; // string | number5、ReturnType
returnType T 的作用是用于获取函数T的返回类型示例
type T0 ReturnType() string; // string
type T1 ReturnType(s: string) void; // void
type T2 ReturnTypeT() T; // {}
type T3 ReturnTypeT extends U, U extends number T; // number[]
type T4 ReturnTypeany; // any
type T5 ReturnTypenever; // any
type T6 ReturnTypestring; // Error
type T7 ReturnTypeFunction; // Error
- 上一篇: 没有网站seo怎么做网店货源一件代发货
- 下一篇: 没有网站百度推广邢台做网站推广报价
相关文章
-
没有网站seo怎么做网店货源一件代发货
没有网站seo怎么做网店货源一件代发货
- 技术栈
- 2026年04月20日
-
没有备案的网站使用微信申请的网站怎么建设
没有备案的网站使用微信申请的网站怎么建设
- 技术栈
- 2026年04月20日
-
没有备案的网站使用微信wordpress中介二手房主题
没有备案的网站使用微信wordpress中介二手房主题
- 技术栈
- 2026年04月20日
-
没有网站百度推广邢台做网站推广报价
没有网站百度推广邢台做网站推广报价
- 技术栈
- 2026年04月20日
-
没有网站备案做流量哪个网站好
没有网站备案做流量哪个网站好
- 技术栈
- 2026年04月20日
-
没有网站可以做app吗响应式网页怎么设计
没有网站可以做app吗响应式网页怎么设计
- 技术栈
- 2026年04月20日
