function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
如上代码所示,需要限制传入的arg类型要保证有length属性,这就需要用到泛型约束。
更改后代码如下
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
extends是继承类,implements是实现接口。
类只能继承一个,接口可以实现多个。
extends继承父类的时候可以重写父类的方法,也可以调用父类的非私有方法;
implements实现接口,必须实现接口的所有方法。
场景:如果一个变量声明的是联合类型,此时就可以使用类型谓词来进行类型保护了
代码如下所示:
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
if (isFish(pet)) {
pet.swim();
}
else {
pet.fly();
}
function padLeft(padding: string | number) {
if (typeof padding === "number") {
}
if (typeof padding === "string") {
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
interface Padder {
getPaddingString(): string
}
class SpaceRepeatingPadder implements Padder {
constructor(private numSpaces: number) { }
getPaddingString() {
return Array(this.numSpaces + 1).join(" ");
}
}
class StringPadder implements Padder {
constructor(private value: string) { }
getPaddingString() {
return this.value;
}
}
function getRandomPadder() {
return Math.random() < 0.5 ?
new SpaceRepeatingPadder(4) :
new StringPadder(" ");
}
// 类型为SpaceRepeatingPadder | StringPadder
let padder: Padder = getRandomPadder();
if (padder instanceof SpaceRepeatingPadder) {
padder; // 类型细化为'SpaceRepeatingPadder'
}
if (padder instanceof StringPadder) {
padder; // 类型细化为'StringPadder'
}
function f(x: number, y?: number) {
return x + (y || 0);
}
上面代码等价于下面的代码
function f(x: number, y?: number|undefined) {
return x + (y || 0);
}
下面的代码没有报错

当在某个变量后边加了!,代表我们告诉ts这个变量不会是undefined或者null
就理解成混入(mixins)就可以了
下面代码中的keyof Person 等价于 ‘name’ | ‘age’
interface Person {
name: string;
age: number;
}
let p: keyof Person; // 'name' | 'age'
就是返回一个对象类型,k代表key T代表val
type Record<K extends string | number | symbol, T> = {
[P in K]: T;
}
生成一个新类型,该类型拥有 T 中的 K 属性集
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
interface Foo {
name: string;
age?: number;
gender: string;
}
type Bar = Pick<Foo, 'age' | 'gender'>
// 相当于
type Bar = {
age?: number
gender: string
}
生成一个新类型,该类型拥有 T 中除了 K 属性以外的所有属性
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
生成一个新类型,该类型与 T 拥有相同的属性,但是所有属性皆为可选项
type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
生成一个新类型,该类型与 T 拥有相同的属性,但是所有属性皆为必选项
type Required<T> = { [P in keyof T]-?: T[P]; }
interface Foo {
name: string
age?: number
}
type Bar = Required<Foo>
// 相当于
type Bar = {
name: string
age: string
}
生成一个新类型,T 中的 K 属性是只读的,K 属性是不可修改的。
type Readonly<T> = { readonly [P in keyof T]: T[P]; }
新类型取T有并且U没有的
type Exclude<T, U> = T extends U ? never : T
type A = number | string | boolean
type B = number | boolean | symbol
type Foo = Exclude<A, B>
// 相当于
type Foo = string
新类型取T有并且U也有的
type Extract<T, U> = T extends U ? T : never
type A = number | string | boolean
type B = number | boolean | symbol
type Foo = Extract<A, B>
// 相当于
type Foo = number | boolean
作用:从泛型 T 中排除掉 null 和 undefined
NonNullable<T>
type NonNullable<T> = T extends null | undefined ? never : T;
type t = NonNullable<'name' | undefined | null>;
/* type t = 'name' */