TypeScript系列:续篇 - 对象类型(含数组、元数组、函数)

在 TypeScript 中,对象类型用于定义对象的形状(shape),即对象包含哪些属性以及这些属性的类型。

对象类型可以是具体的,也可以是抽象的,用于类型检查和类型推断。

对象类型的最基本形式:接口(Interface)类型别名(Type Alias)

🚎 接口 interface :适合定义对象的形状,并且可以被扩展和实现,这使得它在面向对象编程中非常有用。
🚃 类型别名 type :更灵活,可以定义更复杂的类型,包括联合类型、交叉类型、字面量类型和映射类型。

typeinterface
扩展interface B extends A { … }type B = A & { ... }
添加新字段重新定义即可对已声明的type无法添加新属性,可以使用&运算符重新定义一个类型
interface Test {
  a: string;
}
// 向现有接口添加新字段
interface Test {
  b: number;
}
Test // { a: string; b: number; }
  • 同一个属性如果有多个类型声明,彼此不能有类型冲突;
  • 同名方法有不同的类型声明,那么会发生函数重载;后面的定义比前面的定义具有更高的优先级。

属性修饰符

interface Man {
  name: string,
  age?: number;	 // 等价于 age: number | undefined;
  readonly sex: '男';
}

注意:可以使用 ,; 来分隔属性。

  • 属性末尾添加问号 (?) 来将这些属性标记为可选;
  • 属性标记为 readonly 只读,在类型检查期间无法写入。

属性索引1

interface A {
  [prop: string]: number;
}

属性名只要是字符串,都符合类型要求。

‼️ 属性索引仅允许 stringnumbersymbol 、模板字符串模式以及仅包含这些的联合类型。

interface TestAry {
  [index: number]: string;
  length: number;
}

索引类型的一个常见用途是创建映射(map)或字典(dictionary)类型,其中键(key)是字符串,值(value)可以是任意类型。这在处理动态数据结构或配置对象时非常有用。

interface StringMapDemo {
  [key: string]: unknown;
}

泛型对象类型

interface Box {
  contents: any;
}

contents 类型不确定时,设置为 any 有效,但可能发生错误。

if (typeof x.contents === "string") {
	x.contents.toLowerCase()
}

🏇 创建一个通用 Box 类型

interface Box<Type> {
  contents: Type;
}

let numberBox: Box<number> = { contents: 42 };
let stringBox: Box<string> = { contents: 'ligang' };

等价于

interface NumberBox {
  contents: number;
}

interface StringBox {
  contents: string;
}

let numberBox: NumberBox = { contents: 42 };
let stringBox: StringBox = { contents: 'ligang' };

✔️ 使用泛型,当需要一个新类型的 Box 时,根本不需要声明。

注意,类型别名也可以是泛型

type OrNull<Type> = Type | null;
type OneOrMany<Type> = Type | Type[];
type OneOrManyOrNull<Type> = OrNull<OneOrMany<Type>>;
type OneOrManyOrNullStrings = OneOrManyOrNull<string>;

Array 类型

Array 本身是一个泛型类型

function doSomething(value: Array<string>): void {
  // ...
}

Array<string> 等价于 string[]

let arr: (number | string)[];
let arr: Array<number | string>;

元数组

⚽️ 元组类型是另一种 Array 类型,它确切地知道它包含多少个元素,以及它在特定位置包含哪些类型。=> 元组必须明确声明每个成员的类型。

type StringNumberBooleans = [string, number, ...boolean[]];
type StringBooleansNumber = [string, ...boolean[], number];
type BooleansStringNumber = [...boolean[], string, number];
  • StringNumberBooleans 描述了一个元组,其前两个元素分别是 stringnumber,但后面可以有任意数量的 boolean
  • StringBooleansNumber 描述了一个元组,它的第一个元素是 string,然后是任意数量的 boolean,并以 number 结尾;
  • BooleansStringNumber 描述了一个元组,其起始元素是任意数量的 boolean,以 stringnumber 结尾。

函数类型

在声明函数时,需要给出参数的类型返回值的类型

// 方式一
function sayHi(name: string): void {}

// 方式二
const sayHi: (name: string) => void = function (name) {}

// 方式三
type myFunc = (str: string) => void
const sayHi: myFunc = function (name) {}
  • void 类型表示函数没有返回值

可选参数&参数默认值

如果存在可选参数,可选参数只能在参数列表的尾部。

function sayHi(name: string, age?: number): void {}

如果存在参数默认值,可以省略参数类型声明(因为可以从默认值推断出来)。

function sayHi(name = 'ligang'): void {}

可选参数与默认值不能同时使用。

function sayHi(name? = 'ligang'): void {} // 参数不能包含问号和初始化表达式

参数解构

参数结构结合接口(interface)或类型别名(type),更简洁。

// 方式一
function sum({ a, b }: { a: number; b: number }): number {
  return a + b;
}

// 方式二
interface SumParams {
  a: number;
  b: number;
}
function sum({ a, b }: SumParams): number {
	return a + b;
}

rest 参数

rest 参数表示函数剩余的所有参数,它可以是数组(类型相同),也可能是元组(类型不同)。

// rest 参数为数组
function joinNumbers(...nums: number[]) {}

// rest 参数为元组
function f(...args: [boolean, number]) {}

  1. https://typescript.p6p.net/typescript-tutorial/interface.html ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋飛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值