TypeScript技术体系
重要通知
TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。
基本概况
安德斯·海尔斯伯格(Anders Hejlsberg),1960年12月出生于丹麦哥本哈根,曾在丹麦科技大学学习工程学,计算机科学家。Turbo Pascal编译器的主要作者,Delphi、C#和TypeScript之父,.NET(dotnet)创立者。
TypeScript 的目标是成为 JavaScript 程序的静态类型检查器,在JavaScript程序代码运行之前运行(静态)并确保程序类型正确(类型检查)的工具。
tsconfig.json配置编译选项:https://www.tslang.cn/docs/handbook/compiler-options.html
JavaScript与TypeScript区别
- TS是强类型的Javascript超集,它的优势是编译阶段进行类型检查抛出异常,而JS是执行阶段遇到错误才抛出异常。
- 编译耗时,且第三方生态需要同步支持TS。
![]() | ![]() |
安装配置
> pnpm install -g typescript # 安装
> tsc -v # 检查版本
> tsc --init # 制定目录初始化
> tsc --outDir ./dist test.ts # 编译单个文件
> tsc file1.ts file2.ts file3.ts # 编译多个文件
tsconfig.json
{
// 示例
"compilerOptions": {
"composite": true,
"lib": [],
"outDir": "./dist",
"baseUrl": "./",
"paths": {
"@/*": ["*", "src/*"]
},
"alwaysStrict": true,
"noImplicitAny": true,
"removeComments": true,
"allowSyntheticDefaultImports": true, // 允许使用 import Vue from 'vue' 这类语法
"module": "commonjs",
"moduleResolution": "node",
"target": "esnext",
"outDir": "dist",
"strict": true,
"pretty": true,
"sourceMap": true,
"strictPropertyInitialization": true,
"strictNullChecks": true,
"lib": [
"es2017"
]
},
"compileOnSave": false,
"compilerOptions": {
"module": "es2015", // 指定模块是es2015的
"moduleResolution": "node", // 指定路径解析方式用node
"target": "es5", // 指定编译后的js使用es5版本
"lib": [
"dom",
"es5",
"es2015.promise"
],
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@workspace/shared": ["libs/shared/src/index.ts"]
}
// 严格检查的总开关
"strict": true,
// 编译ts出现的版本
"target": "ESNext",
// 模块化版本
"module": "amd",
// 包含的库
"lib": ["DOM", "esnext"],
// outDir用来指定编译后所在的目录
"outDir": "./dist",
// 合并文件只支持amd
"outFile": "./dist/app.js",
// allowJs是否对js文件进行编译,默认是false
"allowJs": false,
// 是否检查js语法是否符合规范,默认是false
"checkJs": false,
// 注释是否编译到js文件,默认false
"removeComments": false,
// 不生成编译后的文件
"noEmit": false,
// 有错误不生成编译文件
"noEmitOnError": false,
// 编译严格模式
"alwaysStrict": true,
// 不允许掩式any
"noImplicitAny": true,
// 不允许不明确的类型this
"noImplicitThis": false,
// 检查空值
"strictNullChecks": true,
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react"
},
"include": [
"src/**/*",
"src/**/*.ts",
"**/**/*.d.ts",
"src/**/*.vue",
"src/**/*.tsx"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
声明文件
TypeScript 作为 JavaScript 的超集,在开发过程中不可避免要引用其他第三方的 JavaScript 的库,需要将这些库里的函数和方法体去掉后只保留导出类型声明,而产生了一个描述 JavaScript 库和模块信息的声明文件。
// 声明文件以 .d.ts 为后缀
declare const count: number;
declare function greet(greeting: string): void;
declare namespace Basic {
function makeGreeting(s: string): string;
let numberOfGreetings: number;
}
// src/declare/images.d.ts
declare module '*.svg'
declare module '*.png'
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.gif'
// src/declare/index.d.ts
declare module 'highlight.js';
// vue-shim.d.ts
declare module '*.vue' {
import { ComponentOptions } from 'vue';
const componentOptions: ComponentOptions;
export default componentOptions;
}
关闭TS校验语句
// @ts-ignore # 忽视本行代码的小错误
// @ts-nocheck # 忽略全文
// @ts-check # 取消忽略全文
特别注意
对于第三方没有声明的TS规范,可以使用yarn add @type/element-plus导入TS声明
类型断言
类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。
- "尖括号"语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
- as语法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
Mixins混合
Mixins混合,即在原有属性与功能的基础进行可复用性添加新的属性或功能等。
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
})
});
}
模块与命名空间
导出语法
// 导出变量
export const
// 导出函数
// 导出接口
// 导出命名空间
// 导出声明
代码示例
a.ts
export namespace Basic {
export interface Vnode {
name: string;
}
}
b.ts
import { Basic } from './a';
function createVnode(vnode: Basic.Vnode) {
console.log('打印');
}
createVnode({ name: '111' });
第二章 基础类型声明
变量
export const toolsList = [];
export type InitHook = (vNode: VNode) => any;
// 字符串
const title: string = "";
const titleList: String[] = [];
// 数字
const count: number = 0;
const countList: Number[] = [];
// 布尔
const close: boolean = false;
const closeList: Boolean[] = [];
// 任意类型
const student: any = {};
//
const student: Record<string, any> = {};
const studentList: Record<string, any>[] = [];
函数
function add(x: number, y: number) {
return x + y;
}
//
function idModel(
id: string | number,
index?: number // 可选属性
) {
//
}
类
interface ClockInterface {
currentTime: Date;
}
class Clock implements ClockInterface {
public title: string; // 公共修饰符可以在实例化、派生类中被访问
private sex: string; // 私有修饰符可以在内部方法中访问
protected total: number; // 受保护修饰符可以在派生类中被访问
static origin = {x: 0, y: 0}; // 静态属性
currentTime: Date;
constructor(h: number, m: number) {
console.info(h, m)
}
run(name = '名称') {
console.info(name)
}
}
const clock = new Clock(1, 2);
clock.run();
枚举
export enum Color {Red = 1, Green = 2, Blue = 4}
类型别名
类型别名和接口的区别
几乎所有的特性interface都可以使用type,主要区别在于type不能重新打开类型来添加新属性,而接口总是可扩展的。
- 类型别名可能不参与声明合并,但接口可以。
// interface
interface Window {
title: string;
}
interface Window {
ts: TypeScriptAPI;
}
const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});
// type
type Window = {
title: string;
}
type Window = {
ts: TypeScriptAPI;
}
// Error: Duplicate identifier 'Window'.
接口只能用于声明对象的形状,不能重命名原语。
接口名称将始终以其原始形式出现在错误消息中,但仅在按名称使用时才出现。
区别举例
// 扩展接口interface
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
// 扩展类型别名type
type Animal = {
name: string;
}
type Bear = Animal & {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
接口
export interface example {
readonly name: string; // readonly修饰符只读属性必须在声明时或构造函数里被初始化。
readonly age: number = 27;
constructor() {
this.name = '张三';
}
}
interface Vnode {
flag: number; // 数字
name: string; // 字符串
list: number[]; // 数组
stack: Array<number>; // 数组泛型
conatiner: [string, number]; // 元组 Tuple
isMount: boolean; // 布尔值
color: Color; // 枚举
type: any; // Any
run: (...args: any[]) => void; // Void
parent: null; // Null
root: undefined; // Undefined
dom: never; // Never
props: object || null; // Object,除number,string,boolean,symbol,null或undefined之外的类型。
}
class createVnode implements Vnode {
//
}
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
keyof
Object.entries(data).forEach((item: any[]) => {
userInfo[item[0] as keyof USER_INFO] = item[1];
});
高级类型
交叉类型(Intersection Types)
交叉类型是将多个类型合并为一个类型。
function extend<T, U>(first: T, second: U): T & U {
let result = <T & U>{};
for (let id in first) {
(<any>result)[id] = (<any>first)[id];
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
(<any>result)[id] = (<any>second)[id];
}
}
return result;
}
联合类型(Union Types)
联合类型表示一个值可以是几种类型之一。
分流
function tsMoule(value: string | number) {
if (typeof value === 'string') {
//
} else {
//
}
}
function stModule(value: string | string[]) {
if (Array.isArray(value)) {
//
} else {
//
}
}
分类
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim(); // errors
类型保护与区分类型
类型保护就是一些表达式,它们会在运行时检查以确保在某个作用域里的类型。
let pet = getSmallPet();
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
}
else {
(<Bird>pet).fly();
}
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
索引类型(Index types)
使用索引类型,通过索引类型查询和索引访问操作符,编译器就能够检查使用了动态属性名的代码。
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
return names.map(n => o[n]);
}
interface Person {
name: string;
age: number;
}
let person: Person = {
name: 'Jarid',
age: 35
};
let strings: string[] = pluck(person, ['name']);
映射类型
在映射类型里,新类型以相同的形式去转换旧类型里每个属性。
type Readonly<T> = {
readonly [P in keyof T]: T[P];
}
type Partial<T> = {
[P in keyof T]?: T[P];
}
type PersonPartial = Partial<Person>;
type ReadonlyPerson = Readonly<Person>;
装饰器
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上,可以用来修改类、方法、属性或参数的行为。
注意事项
VSCode中需要开启experimentalDecorators支持:VSCode -> Preferences -> Settings:experimentalDecorators
- 在tsconfig.json中设置
{
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
}
- 参数装饰器
- 属性装饰器
- 访问器装饰器
- 方法装饰器
- 类装饰器
- 装饰器执行顺序:属性 > 方法 > 方法参数 > 类
HTMLInputElement声明
/*
React projects that don't include the DOM library need these interfaces to compile.
React Native applications use React, but there is no DOM available. The JavaScript runtime
is ES6/ES2015 only. These definitions allow such projects to compile with only `--lib ES6`.
Warning: all of these interfaces are empty. If you want type definitions for various properties
(such as HTMLInputElement.prototype.value), you need to add `--lib DOM` (via command line or tsconfig.json).
*/
interface Event { }
interface AnimationEvent extends Event { }
interface ClipboardEvent extends Event { }
interface CompositionEvent extends Event { }
interface DragEvent extends Event { }
interface FocusEvent extends Event { }
interface KeyboardEvent extends Event { }
interface MouseEvent extends Event { }
interface TouchEvent extends Event { }
interface PointerEvent extends Event { }
interface TransitionEvent extends Event { }
interface UIEvent extends Event { }
interface WheelEvent extends Event { }
interface EventTarget { }
interface Document { }
interface DataTransfer { }
interface StyleMedia { }
interface Element { }
interface DocumentFragment { }
interface HTMLElement extends Element { }
interface HTMLAnchorElement extends HTMLElement { }
interface HTMLAreaElement extends HTMLElement { }
interface HTMLAudioElement extends HTMLElement { }
interface HTMLBaseElement extends HTMLElement { }
interface HTMLBodyElement extends HTMLElement { }
interface HTMLBRElement extends HTMLElement { }
interface HTMLButtonElement extends HTMLElement { }
interface HTMLCanvasElement extends HTMLElement { }
interface HTMLDataElement extends HTMLElement { }
interface HTMLDataListElement extends HTMLElement { }
interface HTMLDialogElement extends HTMLElement { }
interface HTMLDivElement extends HTMLElement { }
interface HTMLDListElement extends HTMLElement { }
interface HTMLEmbedElement extends HTMLElement { }
interface HTMLFieldSetElement extends HTMLElement { }
interface HTMLFormElement extends HTMLElement { }
interface HTMLHeadingElement extends HTMLElement { }
interface HTMLHeadElement extends HTMLElement { }
interface HTMLHRElement extends HTMLElement { }
interface HTMLHtmlElement extends HTMLElement { }
interface HTMLIFrameElement extends HTMLElement { }
interface HTMLImageElement extends HTMLElement { }
interface HTMLInputElement extends HTMLElement { }
interface HTMLModElement extends HTMLElement { }
interface HTMLLabelElement extends HTMLElement { }
interface HTMLLegendElement extends HTMLElement { }
interface HTMLLIElement extends HTMLElement { }
interface HTMLLinkElement extends HTMLElement { }
interface HTMLMapElement extends HTMLElement { }
interface HTMLMetaElement extends HTMLElement { }
interface HTMLObjectElement extends HTMLElement { }
interface HTMLOListElement extends HTMLElement { }
interface HTMLOptGroupElement extends HTMLElement { }
interface HTMLOptionElement extends HTMLElement { }
interface HTMLParagraphElement extends HTMLElement { }
interface HTMLParamElement extends HTMLElement { }
interface HTMLPreElement extends HTMLElement { }
interface HTMLProgressElement extends HTMLElement { }
interface HTMLQuoteElement extends HTMLElement { }
interface HTMLSlotElement extends HTMLElement { }
interface HTMLScriptElement extends HTMLElement { }
interface HTMLSelectElement extends HTMLElement { }
interface HTMLSourceElement extends HTMLElement { }
interface HTMLSpanElement extends HTMLElement { }
interface HTMLStyleElement extends HTMLElement { }
interface HTMLTableElement extends HTMLElement { }
interface HTMLTableColElement extends HTMLElement { }
interface HTMLTableDataCellElement extends HTMLElement { }
interface HTMLTableHeaderCellElement extends HTMLElement { }
interface HTMLTableRowElement extends HTMLElement { }
interface HTMLTableSectionElement extends HTMLElement { }
interface HTMLTemplateElement extends HTMLElement { }
interface HTMLTextAreaElement extends HTMLElement { }
interface HTMLTitleElement extends HTMLElement { }
interface HTMLTrackElement extends HTMLElement { }
interface HTMLUListElement extends HTMLElement { }
interface HTMLVideoElement extends HTMLElement { }
interface HTMLWebViewElement extends HTMLElement { }
interface SVGElement extends Element { }
interface SVGSVGElement extends SVGElement { }
interface SVGCircleElement extends SVGElement { }
interface SVGClipPathElement extends SVGElement { }
interface SVGDefsElement extends SVGElement { }
interface SVGDescElement extends SVGElement { }
interface SVGEllipseElement extends SVGElement { }
interface SVGFEBlendElement extends SVGElement { }
interface SVGFEColorMatrixElement extends SVGElement { }
interface SVGFEComponentTransferElement extends SVGElement { }
interface SVGFECompositeElement extends SVGElement { }
interface SVGFEConvolveMatrixElement extends SVGElement { }
interface SVGFEDiffuseLightingElement extends SVGElement { }
interface SVGFEDisplacementMapElement extends SVGElement { }
interface SVGFEDistantLightElement extends SVGElement { }
interface SVGFEDropShadowElement extends SVGElement { }
interface SVGFEFloodElement extends SVGElement { }
interface SVGFEFuncAElement extends SVGElement { }
interface SVGFEFuncBElement extends SVGElement { }
interface SVGFEFuncGElement extends SVGElement { }
interface SVGFEFuncRElement extends SVGElement { }
interface SVGFEGaussianBlurElement extends SVGElement { }
interface SVGFEImageElement extends SVGElement { }
interface SVGFEMergeElement extends SVGElement { }
interface SVGFEMergeNodeElement extends SVGElement { }
interface SVGFEMorphologyElement extends SVGElement { }
interface SVGFEOffsetElement extends SVGElement { }
interface SVGFEPointLightElement extends SVGElement { }
interface SVGFESpecularLightingElement extends SVGElement { }
interface SVGFESpotLightElement extends SVGElement { }
interface SVGFETileElement extends SVGElement { }
interface SVGFETurbulenceElement extends SVGElement { }
interface SVGFilterElement extends SVGElement { }
interface SVGForeignObjectElement extends SVGElement { }
interface SVGGElement extends SVGElement { }
interface SVGImageElement extends SVGElement { }
interface SVGLineElement extends SVGElement { }
interface SVGLinearGradientElement extends SVGElement { }
interface SVGMarkerElement extends SVGElement { }
interface SVGMaskElement extends SVGElement { }
interface SVGMetadataElement extends SVGElement { }
interface SVGPathElement extends SVGElement { }
interface SVGPatternElement extends SVGElement { }
interface SVGPolygonElement extends SVGElement { }
interface SVGPolylineElement extends SVGElement { }
interface SVGRadialGradientElement extends SVGElement { }
interface SVGRectElement extends SVGElement { }
interface SVGStopElement extends SVGElement { }
interface SVGSwitchElement extends SVGElement { }
interface SVGSymbolElement extends SVGElement { }
interface SVGTextElement extends SVGElement { }
interface SVGTextPathElement extends SVGElement { }
interface SVGTSpanElement extends SVGElement { }
interface SVGUseElement extends SVGElement { }
interface SVGViewElement extends SVGElement { }
interface Text { }
interface TouchList { }
interface WebGLRenderingContext { }
interface WebGL2RenderingContext { }