持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
当你安装 TypeScript 时,会顺带安装一个 lib.d.ts 声明文件。这个文件包含 JavaScript 以及 DOM 的类型声明,以及一些内置的工具类型。它自动包含在 TypeScript 项目的编译上下文中,它能让你快速开始书写经过类型检查的 JavaScript 代码。
const foo = 123;
const bar = foo.toString();
这段代码类型检查正常,同时能获取toString方法的类型,因为 lib.d.ts 为所有 JavaScript 对象定义了 toString 方法。
ts 内置的类型包括如下几种:
全局的类型声明
const a: Array<string> = ['1', '2']
const date = new Date()
date.getTime()
以上类型都是javascript的全局类型声明,在安装ts的时候已经内置了,不需要我们自己安装或者定义。
像这种全局的类型声明,可以理解为构造器声明类型:
- 字符串构造函数类型:StringConstuctor
- 数字构造函数类型:NumberConstuctor
- 对象构造函数类型: ObjectConstuctor
- 数组构造函数类型:ArrayConstructor ...
我们来分析StringConstuctor下的类型声明
interface StringConstructor {
new(value?: any): String;
(value?: any): string;
readonly prototype: String;
fromCharCode(...codes: number[]): string;
}
StringConstuctor 是一个构造函数,所以必须用new(new(value?: any): String;),它返回一个 String类型,那这个 String 接口是怎么样的呢?
interface String {
toString(): string;
charAt(pos: number): string;
charCodeAt(index: number): number;
concat(...strings: string[]): string;
indexOf(searchString: string, position?: number): number;
lastIndexOf(searchString: string, position?: number): number;
localeCompare(that: string): number;
match(regexp: string | RegExp): RegExpMatchArray | null;
replace(searchValue: string | RegExp, replaceValue: string): string;
search(regexp: string | RegExp): number;
slice(start?: number, end?: number): string;
split(separator: string | RegExp, limit?: number): string[];
substring(start: number, end?: number): string;
toLowerCase(): string;
toLocaleLowerCase(locales?: string | string[]): string;
toUpperCase(): string;
toLocaleUpperCase(locales?: string | string[]): string;
trim(): string;
readonly length: number;
substr(from: number, length?: number): string;
valueOf(): string;
readonly [index: number]: string;
}
可以看到在String接口中定义了所有的字符串方法。
内置对象
Math.pow(2, 2)
Math 与其他全局对象不同的是它不是一个构造函数,它的所有属性和方法都是静态的。
DOM 和 Event
DOM 类型声明
在Vue项目中通过template ref获取一个dom节点的时候,就会用到HTMLElement类型声明。
const fileInput = ref<null | HTMLInputElement>(null)
那么这个HTMLInputElement类型是从那来的呢?就是从内置的lib.d.ts文件中来的,我们可以看看它的声明:
interface HTMLInputElement extends HTMLElement {
...
autocomplete: string;
capture: string;
.......
stepUp(n?: number): void;
addEventListener<K extends keyof HTMLElementEventMap>(...) => ...
removeEventListener(...): void;
}
declare var HTMLInputElement: {
prototype: HTMLInputElement;
new(): HTMLInputElement;
};
我们可以看到首先声明了一个接口HTMLInputElement,这个接口里面就定义了input这个dom对象上的属性和方法,同时这个对象继承HTMLElement:
interface HTMLElement extends Element {
......
draggable: boolean;
hidden: boolean;
innerText: string;
lang: string;
......
attachInternals(): ElementInternals;
click(): void;
addEventListener<K extends keyof HTMLElementEventMap>(...) => void;
removeEventListener(...): void;
}
declare var HTMLElement: {
prototype: HTMLElement;
new(): HTMLElement;
};
这个接口又继承自Element,Node, EventTarget,我们来看看EventTarget是什么?
- 是一个最基本的 DOM 接口
- 可以接受事件,创建监听器等实现
interface EventTarget {
addEventListener(
type: string,
callback: EventListenerOrEventListenerObject | null,
options?: AddEventListenerOptions | boolean
): void
dispatchEvent(event: Event): boolean
removeEventListener(
type: string,
callback: EventListenerOrEventListenerObject | null,
options?: EventListenerOptions | boolean
): void
}
根据上面的分析,EventTarget 是最基础的一个父类,当我们获取一个dom实例的时候,就可以利用类型断言来断言出具体的子类如:inputDom as HTMLInputElement。
另外,任何一个dom元素都可以调用addEventListener这个方法了,因为它是继承EventTarget。
Event 类型声明
在开发中,我们经常要处理事件对象 e,那么这个e是什么类型呢?
在vue中开发上传组件时,使用拖拽功能的时候会用到 DragEvent 这个类型
const handleDrag = (e: DragEvent) => {
e.preventDefault()
}
// 类型声明文件
interface DragEvent extends MouseEvent {
readonly dataTransfer: DataTransfer | null;
}
interface MouseEvent extends UIEvent
interface UIEvent extends Event
我们可以发现事件对象e也是这样一层一层继承自根接口Event。
比较常用的事件类型如下:
- 鼠标对象类型:
MouseEvent - 键盘事件类型:
KeyboardEvent - 普通事件类型:
Event
内置工具类型
在使用TypeScript进行开发时,大部分时间我们都是自定义类型,但是TypeScript也有很多内置类型,我们如果对其足够熟悉,那么将可以大大提高我们的开发效率。
Partial
该工具函数可以构造一个新类型,将类型参数 T 中的所有属性变为 可选属性。
interface Person {
name: string
age: number
}
type PartialType = Partial<Person> // { name ?: string; age ?: number }
Required
该工具函数可以构造一个新类型,将类型参数 T 中的所有属性变为 必选属性。
interface Person {
name: string
age?: number
}
type RequiredType = Required<Person> // { name: string; age: number }
const student1: RequiredType = {
name: 'zhangsan',
age: 18
}
const student2: RequiredType = { // 错误,缺少 age 属性
name: 'lisi'
}
cosnt student3: RequiredType = { // 错误,缺少 name 属性
age: 18
}
Readonly
该工具函数可以构造一个新类型,将类型参数 T 中的所有属性变为 只读属性。
interface Person {
name: string
age?: number
}
type ReadonlyType = Readonly<Person> // { readonly name: string; readonly age: number }
const student1: ReadonlyType = {
name: 'zhangsan',
age: 18
}
student1.name = 'lisi' // 编译错误,不允许修改;name 属性为只读属性
student1.age = 20 // 编译错误,不允许修改;age 属性为只读属性
Record<K, T>
该工具类型可以构造一个新的对象类型。类型参数 K 提供了对象属性名联合类型,类型参数 T 提供了对象属性值的类型。
简单来说,Record<K, T> 可以快速创建一个 “键类型为 K、值类型为 T” 的对象类型,避免手动逐个定义属性。
type K = 'x' | 'y'
type T = number
type R = Record<K, T> // { x: number; y: number }
const a: R = { x: 0, y: 0 } // key 必须为x或者y,value必须是数字类型
Pick<T, K>
该工具类型可以从已有的对象类型中选取指定的属性及其类型,然后构建出一个新的对象类型。
类型参数 T 表示源对象的类型,类型参数 K 提供了待选取的属性名类型,它必须是对象类型 T 中存在的属性。
interface Person {
name: string
age: number
}
type PickName = Pick<Person, 'name'> // { name: string }
type PickAge = Pick<Person, 'age'> // { age: number }
type PickAll = Pick<Person, 'name' | 'age'> // { name: string; age: number }
type PickError = Pick<Person, 'sex'> // 错误,类型 Person 中不存在 sex 属性
Omit<T, K>
该工具类型的作用与 Pick<T, K> 是互补的,能够从已有的对象属性中剔除指定的属性,然后构建出一个新的对象类型。
类型参数 T 表示源对象的类型,类型参数 K 提供了待剔除的属性名的类型,但是它可以是类型参数 T 中不存在的属性。
interface Person {
name: string
age: number
}
type OmitName = Omit<Person, 'name'> // { age: number }
type OmitAge = Omit<Person, 'age'> // { name: string }
type OmitAll = Omit<Person, 'name' | 'age'> // {}
type OmitNone = Omit<Person, 'z'> // { name: string; age: number }
Exclude
当想从一个联合类型中去掉一部分类型时,可以用 Exclude 进行构造。它与 Pick 及 Omit 的区别是它剔除联合类型里面的类型,后者是剔除接口里面的类型。
type Exclude<T, U> = T extends U ? never : T;
// test
const n: Exclude<"a" | "b" | "c" | "d" | "e", "a" | "c"> = "b";
// const n:"b" | "d" | "e"
Extract
取两个联合类型的交集。
const m: Extract<"a" | "b" | "c" | "d" | "e", "a" | "c"> = "c"; //const m: "a" | "c"
NonNullable
该工具类型能够从类型参数 T 中剔除 null 类型和 undefined 类型,并构建一个新的类型。即获取类型 T 中的所有非空类型。
type NonNull0 = NonNullable<string, null, number> // string, number type NonNull1 = NonNullable<string[], null, undefined> // string[]
Parameters
该工具类型能够获取函数类型 T 的参数类型并使用参数类型构造一个元组类型。
type Parameters0 = Parameters<() => string> // []
type Parameters1 = Parameters<(s: string) => void> // [string]
ReturnType
该工具类型能够获取函数类型 T 的返回值类型。
type ReturnType0 = ReturnType<() => string> // string
type ReturnType1 = ReturnType<() => { a: number; b: string}> // { a: number; b: string}