TS 常见类型用法

93 阅读2分钟

interface

接口一方面可以在面向对象编程中表示为行为的抽象,另外可以用来描述对象的形状。

interface Point {
  x: number;
  y:number;
}

let p1: Point = { x: 10, y: 20 };

接口能够描述JavaScript中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。

interface SearchFunc {
  (source: string, subString: string): boolean;
}

这样定义后,我们可以像使用其它接口一样使用这个函数类型的接口。 下例展示了如何创建一个函数类型的变量,并将一个同类型的函数赋值给这个变量。

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
  let result = source.search(subString);
  return result > -1;
}

对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配。

可索引的类型

可索引的类型与使用接口描述函数类型差不多,可以描述那些能够“通过索引得到”的类型,让我们看一个例子:

数组里面的元素。

interface StringArray {
  [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];

对象任意属性,无法预先知道有哪些新的属性的时候,可以使用 [propName:string]:any,propName 名字是任意的。

interface Person {
  readonly id: number;
  name: string;
  [propName: string]: any;
}

const obj = {
  id:1,
  name:'hello',
  age:10
}

泛型约束

在函数中使用泛型的时候,由于预先并不知道泛型的类型,所以不能随意访问相应类型的属性或方法。

function logger<T>(val: T) {
  console.log(val.length); // 直接访问会报错
}

为此,我们定义一个接口来描述约束条件。 创建一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束:

// 可以让泛型继承一个接口
interface LengthWise {
  length: number
}

// 可以让泛型继承一个接口
function logger2<T extends LengthWise>(val: T) {
  console.log(val.length)
}
logger2('hello');

keyof

首先是 keyof T, 索引类型查询操作符。 对于任何类型 T, keyof T 的结果为 T 上已知的公共属性名的联合。

interface Person{
  name:string;
  age:number;
}
//type PersonKey = 'name'|'age';
type PersonKey = keyof Person;

keyof Person 是完全可以与 'name' | 'age' 互相替换的。 不同的是如果你添加了其它的属性到 Person,例如 address: string,那么 keyof Person 会自动变为 'name' | 'age' | 'address'

TypeScript 中也有 typeof 运算符,使用该运算符来引用变量或属性的类型:

const Person = {
  name: 'hello',
  age: 18,
  gender: 'male'
}

//type PersonKey = {name:string,age:number,gender:string};
type PersonKey = typeof Person

//type PersonKey = 'name'|'age'|'gender';
type PersonKey = keyof typeof Person

获取函数返回值的类型:

function f() {
  return { x: 10, y: 3 };
}

//type P = {x:number,y:number}
type P = ReturnType<typeof f>;

索引访问类型

我们可以使用索引访问类型来查找另一种类型的特定属性:

interface User {
  name: string,
  age: number,
  info: {
    title: string
  }
}

//type Info = {title:string}
type Info = User['info']

//type I1 = number|string
type I1 = User["age" | "name"];