# LearningTypeScriptTheHardWay **Repository Path**: guojialin/learning-type-script-the-hard-way ## Basic Information - **Project Name**: LearningTypeScriptTheHardWay - **Description**: 学习TypeScript的记录 - **Primary Language**: TypeScript - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-11-06 - **Last Updated**: 2021-11-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 学习TypeScript的笔记 ## 1. Typescript 编译命令 可以省略 tsconfig.json ```json { "compilerOptions": { "outDir": "./dist", "target": "ES5", "watch": true }, "include": [ "./src/**/*.ts", "./src/**/*.js" ] } ``` ts命令 ```shell tsc --outDir ./dist --target es6 ./src/basic.ts --watch ``` ## 2. 静态类型语言与动态类型语言 ### 2.1优缺点比较 | | 动态类型语言 | 静态类型语言 | | -------- | ------------ | ------------------------------------- | | 编译 | | 配合IDE和在编译期可以发现一些潜在错误 | | 编码规范 | | 有利于大型项目开发 | | 类型提示 | | | | 文档 | | 代码即文档 | ### 2.2 什么是类型系统 #### 类型标注与类型检测 1. 类型标注 (定义、注解) 1. 类型标注后不能再存储或传入与类型不符合的类型 2. 类型检测 #### 什么是类型保护? typeof 基础类型做类型推断 ```typescript function fn(a: string | number) { // a.substring(1,2) // 类型“number”上不存在属性“substring”。 // ( a).substring(1,2) // 有风险 if(typeof a === 'string') { a.substring(1); } else { a.toFixed(1) } } ``` instanceof 对象实例的类型推断 ```typescript function fn2(a: Date | Array) { if (a instanceof Array) { a.push(1) } else { a.getFullYear(); } } ``` in 包含属性的类型推断 ```typescript function fn3(arg: IA | IB) { if ('x' in arg) { // ok arg.x // error arg.y } else { // ok arg.a // error arg.x } } ``` 自定义类型推断 ```typescript function fn4(elements: Element[] | NodeList | Element) { if (canEach(elements)) { elements.forEach(elements => { elements.className = '' }) } else { elements.className = '' } } /** * 添加了 `is` 作为类型谓词 * @param data * @returns 返回bool */ function canEach(data: any): data is Element[] | NodeList { return data.forEach !== undefined; } ``` ### 2.3 TS的基础类型 #### 基础类型 #### 空和未定义类型 #### 对象类型 #### 数组类型 #### 元组类型 #### 枚举类型 #### 无值类型 #### Never类型 #### 任意类型 #### 未知类型 ### 2.4 函数 函数定义 ```typescript // 1. 简单模式 function func1(a: string): string { return ''; } // 2. function值表示 let func2: (a: string) => string = function(a:string): string { return '' } // 3. 封装function的类型 type callback = (a: string) => string; let func3: callback = function(b) { return '' } // 4. interface封装的写法 interface ICallback { (a:string): string } let func4: ICallback = function(c) { return '' } ``` 函数可选参数 ```typescript // ? 代表可选参数 function css(el: HTMLElement, attr: string, val?: any) { } let div = document.querySelector('div'); div && css(div, 'width', '100px') div && css(div, 'width') ``` 函数默认值 ```typescript // 函数参数默认值,默认值带有类型推到 function sort(items: Array, order = 'desc') { } sort([1, 2, 3]) sort([1, 2, 3], 'asc') ``` ```typescript // 参数默认值限制取值 function sort2(items: Array, order: 'desc' | 'asc' = 'desc') { } ``` 剩余参数 ```typescript // 剩余参数 interface IObj { [key: string]: any; } function merge(target: IObj, ...others: Array) { // 浅拷贝 Object.assign 属性“assign”在类型“ObjectConstructor”上不存在。是否需要更改目标库? // 请尝试将 “lib” 编译器选项更改为“es2015”或更高版本。 // 添加: // "compilerOptions": { // "target": "ES5", // "lib": [ "dom", "es5", "es2015.promise" ,"es2015", "es2017"], // }, return Object.assign(target, ...others); } function merge2(target: IObj, ...others: Array) { return others.reduce((prev, current) => { prev = Object.assign(prev, current); return prev; }, target) } let newObj = merge({ x: 1 }, { y: 2 }, { z: 3 }) let newObj2 = merge2({ x: 1 }, { y: 2 }, { z: 3 }) ``` ### 2.5 接口 做类型定义 ```typescript interface Point { x: number; y: number; } let p1: Point = { x: 100, y: 100 } interface Point2 { readonly x: number; y: number; color?: string; } let p2: Point2 = { x: 100, y: 100, color: 'red' } // 无法分配到 "x" ,因为它是只读属性。 // p2.x = 200 // interface P3 { // // 类型“string | undefined”的属性“color”不能赋给“string”索引类型“number”。ts(2411) // color?: string; // [key: string]: number; // } // 保留Point3的扩展能力 interface Point3 { readonly x: number; y: number; [key: string]: number; } let p3: Point3 = { x: 1, y: 2, } p3.good = 3 p3.try = 4 // key的类型可以是number或者string, number需要用下标表示 interface Point4 { readonly x: number; [key: number]: string; } let p4: Point4 = { x: 1000 } p4[0] = 'nice try'; p4[2] = 'nice try2'; // key的值类型必须是下面值类型的父类型 interface Point5 { // [key: string]: string; // error:上面key的值类型必须是下面值类型的父类型 [key: string]: Object; [key: number]: number; } class Person { constructor(public username: string) { } } class Student extends Person { } interface Point6 { // [key: string]: string; // error:上面key的值类型必须是下面值类型的父类型 [key: string]: Person; [key: number]: Student; } ``` ### 2.6 类