# ts-example **Repository Path**: jonnyjiang/ts-example ## Basic Information - **Project Name**: ts-example - **Description**: No description available - **Primary Language**: TypeScript - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-06-18 - **Last Updated**: 2024-06-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 创建ts项目 1. 创建项目目录 ```shell mkdir xxx ``` 2. 初始化npm: ```shell cd xxx && npm init -y ``` 3. 安装ts依赖: ```shell npm install --save-dev typescript ``` 4. 安装babel编译ts ```shell npm install --save-dev @babel/core @babel/cli @babel/plugin-proposal-class-properties @babel/preset-env @babel/preset-typescript ``` 5. 创建、配置 tsconfig.json ```shell tsc --init --declaration --allowSyntheticDefaultImports --target esnext --outDir lib ``` 参考: ```json { "compilerOptions": { "target": "es5", "lib": ["es6"], "module": "commonjs", "rootDir": "./", "resolveJsonModule": true, "allowJs": true, "outDir": "build", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitAny": true, "skipLibCheck": true, }, "include": ["src/**/*.ts", "src/**/*.d.ts"], "exclude": [ "node_modules", "**/*.spec.ts" ] } ``` 6. 创建babel配置文件`.babelrc` ```json { "presets": [ "@babel/preset-env", "@babel/preset-typescript" ], "plugins": [ "@babel/plugin-proposal-class-properties" ] } ``` 7. 配置启动脚本 ```json "scripts": { "type-check": "tsc --noEmit", "type-check:watch": "npm run type-check -- --watch", "build": "npm run build:types && npm run build:js", "build:types": "tsc --emitDeclarationOnly", "build:js": "babel src --out-dir dist --extensions \".ts,.tsx\" --source-maps inline", "start": "npm run build && node dist/index.js" }, } ``` 8. 启动 ```shell npm run start ``` 9. 直接执行ts——ts-node 按照ts-node ```shell $ npm i ts-node typescript -g ``` 修改启动配置文件 ```json "scripts": { "type-check": "tsc --noEmit", "type-check:watch": "npm run type-check -- --watch", "build": "npm run build:types && npm run build:js", "build:types": "tsc --emitDeclarationOnly", "build:js": "babel src --out-dir dist --extensions \".ts,.tsx\" --source-maps inline", "start": "ts-node src/index.ts" } ``` # ts学习 ## interface ```typescript // interface是一种约定、规范 // interface 可以是属性集也可以表示一类函数 // interface 可以定义接口的抽象、规范待子类实现 interface Person { readonly name?: string; readonly age?: number; [propName:string]:any; // 使用索引签名,使得可以添加任意属性 } function printPerson(person: Person) { console.log(person); } /** * 1. 绕过ts类型检查 “as” : { namee: "Jack", age: 32 } as Person * 2. 绕过ts类型检查 临时变量中转 */ // 临时变量中转会绕过ts类型检查 // const person = { namee: "Jack", age: 32 } // printPerson(person); // 使用类型签名 printPerson({ name: "Jack", age: 32,gender:"Male"}); // 定义interface为一类操作两个数的函数 interface OperationTwoNum { (a: number, b: number): number; } // 定义一个加法函数 const add:OperationTwoNum = (a: number, b: number) => a + b; /** * 1. 传入的参数必须是OperationTwoNum类型 * 2. 传入的参数必须是两个数 * 3. 返回值必须是一个数 * @param operation * @param a * @param b * @returns */ function caculate(operation:OperationTwoNum, a: number, b: number) { return operation(a, b); } // interface可以作为可索引类型 interface NumberArray { readonly [index: number]: number; } // 可以同时设置string和number索引,但是number索引的返回值必须是string索引返回值的子类型 interface StringArray{ [key:string]:Object; [key:number]:Object; } const arr:NumberArray = [1, 2, 3, 4, 5]; const arr2:StringArray = {1:"1",2:"2",3:"3",4:"4",5:"5"}; // interface可以继承、被继承、被实现 interface Eat{ eat():void; } interface Run{ run():void; } class Dog implements Eat,Run{ eat(){ console.log("Dog eat"); } run(){ console.log("Dog run"); } } // interface混合类型 interface Handler{ (req:any,res:any):void; ctx:any } function getHandler():Handler{ const handler = (req:any,res:any)=>{ console.log(req,res); } handler.ctx = {}; return handler; } // interface: 静态、实例部分 // 表示构造函数 为静态 interface TwoNumConstructor{ new (a:number,b:number):any; } // 表示实例部分 interface TwoNumInstance{ add():number; } class TwoNum implements TwoNumInstance{ constructor(a:number,b:number){ this.a = a; this.b = b; } a:number; b:number; add(){ return this.a + this.b; } } function createTwoNum(ctor:TwoNumConstructor,a:number,b:number):TwoNumInstance{ return new ctor(a,b); } ``` ## class ```typescript // 修饰符 readonly、public、private、protected class Student{ // 参数属性使得在一个地方 定义和初始化成员 constructor(readonly name:string, readonly age:number){} } const stu = new Student("jonny",123); // 提取器:通过get、set实现属性的读取。 class Gamer{ private _name:string; private _age:number; constructor(name:string, age:number){ this._name = name; this._age = age; } get name(){ return this._name; } set name(value:string){ this._name = value; } get age(){ return this._age; } set age(value:number){ if(value<0){ throw new Error("年龄不能为负数"); } this._age = value; } } const gamer = new Gamer("jonny",123); gamer.age = 123; gamer.name = "jonny"; console.log(gamer) // 抽象类 // static静态属性 // 类的继承 // 可以在使用interface的地方使用class ``` ## 泛型 ```typescript function identity(arg: T): T { return arg; } // 箭头函数也可以定义泛型 // const myIdentity: (arg: U) => U = identity; // 也可以通过函数签名来定义 const myIdentity: {(arg: U): U} = identity; // 定义一个泛型接口。 // 注意:此时没有指定属性的名称,即表示当前interface为对应的别名 interface Identity{ (arg:T):T; } // 在使用的时候可以指定具体的类型 const myIdentity2:Identity= identity; // 泛型类 class Printer{ constructor(private readonly content:T) { } print(){ console.log(this.content); } } const p1 = new Printer(1); p1.print(); const p2 = new Printer("hello"); p2.print(); // ======= 泛型约束 /** * 定义一个带有length属性的interface */ interface LengthAble{ length:number } /** * 需要一个有length属性的参数,但是不限定类型,于是使用接口作为范围边界 * @param arg */ function printLength(arg:T){ console.log(`length is ${arg.length}`); } printLength([]); // printLength(1); // error。number没有length属性 ``` ## 高级类型 ```typescript // 类型 限定 function isNumber(x: any): x is number { return typeof x === "number"; } function isString(x: any): x is string { return typeof x === "string"; } function padLeft(value: string, padding: string | number) { if (isNumber(padding)) { return Array(padding + 1).join(" ") + value; } if (isString(padding)) { return padding + value; } throw new Error(`Expected string or number, got '${padding}'.`); } // 类型别名 type ArrayNumber = Array; // ===== 索引查询操作符、索引访问操作符 interface Student{ name:string, age:number } const stu = {name:"jonny",age:1}; // 索引查询操作符 keyof const key:keyof Student = 'name'; // 索引访问操作符: T[K] T为类型,K为key名称 const val:Student[keyof Student] = stu.name; /** * 获取对应key的value * @param obj * @param keys */ function values(obj:T,keys:K[]):T[K][]{ return keys.map(key => obj[key]); } // key需要为单引号 const vals = values(stu,['name']); // 映射类型 /** * 遍历key,如果值有就取否则为null */ type Nullable = { [K in keyof T]: T[K] | null } /** * 遍历所有属性,都加上“?” */ type MyPartial = { [K in keyof T]?:T[K]; } /** * 遍历所有的属性 都加上“readonly” */ type ReadOnly = { readonly [K in keyof T] : T[K]; } /** * 提取两个类型共有的属性创建一个新类型 */ type CommonType = { [K in keyof T]: K extends keyof T ? K extends keyof U ? T[K] : never : never } type StudentPartial = Partial; type NullStudent = Nullable; type PartialStudent = MyPartial; type ReadOnlyStudent = ReadOnly; interface Pet{ name:string, age:number, master:string } type CommonStuPerson = CommonType; const commonStuPerson:CommonStuPerson = { name:'jonny', age:1 } console.log(); type CommonNewType = Exclude< {id:number,name:string,status:boolean}, {id:number,status:boolean,time:number} >; ``` ## 元组 元组可以进一步提升数组结构的严谨性。 ```shell type Point = [x:number, y:number]; const p = [1,2] as Point; function printPoint(point:Point){ console.log(point); } printPoint(p); ``` ## object、Object、{} 1. object表示非基本类型 2. Object所有类型的基类 3. {}表示任何非 `null|undefined`的值,不能访问里面的属性 ## 字面量类型、组合类型 ```typescript // 字面量类型、组合类型 interface Person { gender: 'Male' | 'Female', name: string, age: number, country: | { china: true, dosomething: string } | { china: false, apply: string } } const person: Person = { gender: 'Female', name: 'zhangsan', age: 18, country: { china: true, dosomething: "just do it" }, } // 要确定了chinal的值后,才能确定具体的类型 if (person.country.china) { console.log(person.country.dosomething); } else { console.log(person.country.apply); } ```