7TypeScript中的对象与函数

49 阅读4分钟

一. 如何定义对象的类型

  • 方式1.最基础的方式
type Person = {
  name: string;
}; // 要注意这种定义的Person类型范围很大,包含 {name: string, age: 18} 等只要有{name: string}的类型。

interface Person {
  name: string;
}
  • 方式2. 索引签名
type Hash = {
  [k: string]: unknown;
  length: number;
};
// k 表示key可以用其它任意字母或者单词替代,第一个冒号后面描述key的类型,第二个冒号后面为value的类型
// 还可以写其它的类型,比如length表示所有下标的个数
type List = {
  [k: number]: unknown;
  length: number;
};
  • 方式3. 映射类型,这种方式和方式2的主要区别,1. 不能加其它属性比如length 2. 主要用于范型
type Hash = {
  [k in string]: unknown;
};

type List = {
  [k in number]: unknown;
};

二. 其它一些对象的语法

    1. 问号表示可选
interface InputProps { 
  defaultValue?: string;
  value?: string;
  onChange?: () => void;
}

const propsInputProps = {}; // 什么都不写也不会报错
    1. readonly语法
interface User {
  readonly id: number;
  readonly name: string;
  readonly scores: number[];
  age?: number;
}

const u: User = {
  id: 1,
  name: 'Jack',
  scores: [98, 99],
};

u.id = 2; // 会报错,不能改id
s.scores = [100100]; // 会报错
u.scores[0] = 100; // 通过下标改这样不会报错,说明readonly只管道scores这一层,不保证里面的属性不可更改
u.scores[1] = 100;

三. 深入函数语法

    1. 对象的语法全都适用于函数
type F = {
  (anumberbnumber): number;
  countnumber;
};
// 也可以用interface,完全一样,type和interface之前的文章已经详细描述过
interface F2 {
  (anumberbnumber): number;
  readonly count?: number;
}

const f: F = (x, y) => {
  return x + y;
};

f.count = 1;

// 等价于
type F1 = (a: number, b: number) => number;
// 这两者的区别,如果只是想简单声明函数就用下面F1这种,如果想要加属性,用上面一种

四. 函数的所有声明方式,这里主要关注函数的值和类型

  • 回顾js中的三种函数写法
// js中函数的三种生命方式

// 1.函数声明
function f1(a) {}

// 2.函数表达式也叫匿名函数赋值
const f2 = function (a) {};

// 3.箭头函数
const f3 = (a) => {};
  • ts中对应的写函数的方法
function f1(a: number): number {
  return a + 1;
}

// 有两种写发对应js中的第二种声明方式
// 1. 写等号右边
const f2 = function (a: number): number {
  return a + 1;
};

// 2. 写等号左边
type F2 = (x: number) => number;
const f2F2 = function (a) {
  return a + 1;
};
// 同样箭头函数也有两种对应写法
// 1. 写等号右边
const f3 = (anumber): number => {
  return a + 1;
};
type F3 = (x: number) => number;

// 2. 写等号左边
const f3F3 = (a) => {
  return a + 1;
};
// 总结: 建议左右两边写一种就可以
  • 总结声明函数和类型的方式,推荐第一种,可以帮助培养类型优先的思维方式
// 第一种: 先写类型再赋值
type F1 = (a: number, b: number) => number;
const f1F1 = (a, b) => a + b;

// 第二种: 先实现箭头函数,再获取类型
const f2 = (anumberbnumber): number => {
  return a + b;
};
type F2 = typeof f2;

// 第三种: 先实现普通函数,再获取类型
function f3(thisunknown, a: number, b: number): number {
  return a + b;
}
type F3 = typeof f3;

// 第四种: 先实现匿名普通函数,再获取类型
const f4 = function (thisunknown, a: number, b: number): number {
  return a + b;
};

type F4 = typeof f4;

// 第五种: 非常不常见,基本没人写,一般用于写库的场景,也无法指定类型
const f5 = new Function('a''b''return a + b');
type F5 = typeof f5;

五. 两种特殊的函数

    1. 构造函数,后面再研究
    1. 类型谓词,之前文章有介绍过
// js自带的类型收窄
function f1(a: string | string[]{
  if (a instanceof Array) {
    a;
  } else {
    a;
  } 
}

// 如果是对象类型

type Person = {
  name: string;
};
type Animal = {};
function f2(a: Person | Animal{
  if (isPerson(a)) {
    a; // a的类型被收窄为Person
  }
}

// 注意:通过x is Person将函数和Person类型进行关联
function isPerson(x: Person | Animal): x is Person {
  if ('name' in x) {
    return true;
  } else {
    return false;
  }
}
// 如果是箭头函数,那么类型只能写右边
const isPerson2 = (x: Person | Animal): x is Person => 'name' in x;

六. ts函数的一些细节

    1. 可选参数
function addEventListener(
  eventType: string,
  fn: unknown,
  useCapture?: boolean
) {
  // 浏览器实现
  console.log(eventType, fn, useCapture);
}

addEventListener('click'() => 1);
    1. 参数默认值
function addEventListener(eventType: string, fn: unknown, useCapture = false) {
  // 浏览器实现
  console.log(eventType, fn, useCapture);
}

addEventListener('click'() => 1);
    1. 参数是函数
function addEventListener(
  eventType: string,
  fn: (this: HTMLElement, e: Event) => void,
  useCapture?: boolean
) {
  const element = {} as HTMLElement;
  const event = {} as Event;
  fn.call(element, event);
  // 浏览器实现
  console.log(eventType, fn, useCapture);
}

addEventListener('click'() => 1);  
    1. 返回值也是函数,也就是函数的柯里化
const add = (a: number, b: number) => a + b;

type CreateAdd = (x: number) => (y: number) => number;
const createAddCreateAdd = (a) => (b) => a + b;

const f = createAdd(6)(14); // 20
// 实际应用中的例子,Redux
// connect({map:{}}) (Component)