前言以下的内容是19年学习的笔记,19年的时候ts的项目还用得少,今年再回头看这份文档又有一些加深的理解,如果你正在学习typescript希望对你有所帮助
TS入门学习资料「1.9W字总结」一份通俗易懂的 TS 教程,入门 + 实战!本文大量使用了TS入门学习资料的范例并且加以理解,但是也有省略很多的关键点,如需完整学习请移植上方链接什么是 Typescript&为什么选择TS
- 包容
- 类型定义系统
- 学习曲线高
- 编译
- 源码定义
- 复杂&构建流程
npm install -g typescript
tsc xxx.ts
- 编辑器
vscode
webstorm
balabala
vscode 调试 Typescript- 我们学习测试的时候可以直接选择不编译为js,可以直接在vscode来调试ts文件
npm install typescript --save-devnpm install ts-node --save-dev
废弃下面调试!!! 已经过时配置 tsconfig.json主要是将 sourceMap 设置为true。{"compilerOptions": { "module": "commonjs", "target": "es5", "noImplicitAny": true, "outDir": "./dist", "sourceMap": true},"include": [ "src*"]}
配置 launch.json打开 DEBUG 界面,添加 配置 或者编辑 /.vscode/launch.json。
{"version": "0.2.0","configurations": [ { "name": "Current TS File", "type": "node", "request": "launch", "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", "args": [ "${relativeFile}" ], "cwd": "${workspaceRoot}", "protocol": "inspector" }]}
最新调试方法ts-node-gayhubVisual Studio CodeCreate a new node.js configuration, add -r ts-node/register to node args and move the program to the args list .{"type": "node","request": "launch","name": "Launch Program","runtimeArgs": [ "-r", "ts-node/register"],"args": [ "${workspaceFolder}/index.ts"]}
直接配置为launch.json 其中args配置为自己想要调试的文件Hello Typescriptfunction sayTs{console.log}sayTs
如果没有传递name为字符串比如number类型或者其他类型则会报错原始数据类型原始数据类型包括:布尔值、数值、字符串、null、undefined 以及 ES6 中的新类型 Symbol。Booleanconst isBoolean:Boolean = false;console.log; // boolean
numberconst isNumber:Number = 123;console.log; // number
stringconst isString:String = 'soul';console.log; // string
void 空值Javascript 没有空值(Void)的概念,在 Typescript 中,可以用 void 表示没有任何返回值的函数:const isVoid:void = null;console.log; // object
声明一个 void 类型的变量没有什么用,因为你只能将它赋值为 undefined 和 null;null在js中是object,不过我建议所有的定义类型都用小写,比如isVoid:void
中的void
用的是小写。大写其实是用到了js相关的基本类型null&undefinedlet u: undefined = undefined;let n: null = null;// 这样不会报错let num: number = undefined;
null&undefined是所有类型的子集,所以你定义了一个number
类型的 后面赋值为undefined
是没什么问题的any 任意值如果是一个普通类型,在赋值过程中改变类型是不被允许的:let myFavoriteNumber: string = 'seven';myFavoriteNumber = 7;// index.ts: error TS2322: Type 'number' is not assignable to type 'string'.
但如果是 any 类型,则允许被赋值为任意类型。let myFavoriteNumber: any = 'seven';myFavoriteNumber = 7;
- -所以说 any类型的这个基本上跟你写js是一样的
let myFavoriteNumber = 'seven';myFavoriteNumber = 7;// index.ts: error TS2322: Type 'number' is not assignable to type 'string'.
上面的代码虽然会编译报错,但是TS在分析你代码的时候 会推论成当前变量后面跟了一个字符串 所以还是会把此变量定义为string类型联合类型let isUnion:string|number|object;isUnion = '123';isUnion = {};isUnion = 455;
通过定义的时候以|
分隔 来定义当前变量可以允许多种类型对象的类型——接口interface User{name:string,token:string|number,info :string // 为可选属性 [propName: string]: any; readonly id: number; // 只读属性 在接口第一次实现的时候就需要赋值, 比如 let u1:User = {id:233},这里已经实现好了 再次赋值就不行 比如u1.id=255;}let u2 = {id:233,name:'soul',info:'c',extra:'2'}console.log
这里几个关键词- 只读属性
- 可选属性
- 接口定义的类型[propName]
- 创建数组
let array1:number[] = [1,2,3];let array2:Array = [4,5,6]
两种方式都可以创建数组,其中number
规定了数组的子元素只能是number
类型- 类数组
function sum {let args: { [index: number]: number; length: number; callee: Function;} = arguments;}
arguments在js中不是一个数组类型,那么这个时候就可以来定义类数组了。[index:number] // 规定索引为number类型,那么其中数组中的元素必须都得为number类型
事实上常用的类数组都有自己的接口定义,如 IArguments, NodeList, HTMLCollection 等 这些已经是在ts内置对象中已经定义好了function sum {let args: IArguments = arguments;}
函数的类型function sum1: number {return x + y;}sum1; // 传递的时候 参数必须匹配 多一个少一个都不行// : number 规定了函数返回的类型为number
关键词 - 函数参数类型定义 - 函数返回定义函数表达式let mySum = function : number {return x + y;};
上面虽然可以通过编译 但实际上mySum
变量是通过ts类型推导出来的 严格意义的定义如下let mySum: => number = function : number {return x + y;};
这里的箭头函数跟es6的箭头函数不一样 在 Typescript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。用接口定义函数输入&输出// 接口形式定义interface SearchFunc {: boolean;}let mySearch: SearchFunc;mySearch = function {return source.search !== -1;}
- 可选参数&默认参数&剩余参数
// 可选参数function t1:string{console.log;return name+sex+age}console.log) // soul男18
如果有默认值的话 自动为可选参数,通过用...扩展符则可以获取到剩余的传递的参数类型断言function getLength: number {if { return something.length;} else { return something.toString.length;}}// index.ts: error TS2339: Property 'length' does not exist on type 'string | number'.// Property 'length' does not exist on type 'number'.// index.ts: error TS2339: Property 'length' does not exist on type 'string | number'.// Property 'length' does not exist on type 'number'.
在使用变量判断的时候 ts不知道当前值是string还是number,这个时候可以用到类型断言function getLength: number {if .length) { return .length;} else { return something.toString.length;}}
类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的。声明文件新语法索引由于本章涉及大量新语法,故在本章开头列出新语法的索引,方便大家在使用这些新语法时能快速查找到对应的讲解:
- declare var 声明全局变量
- declare function 声明全局方法
- declare class 声明全局类
- declare enum 声明全局枚举类型
- declare namespace 声明(含有子属性的)全局对象
- interface 和 type 声明全局类型
- export 导出变量
- export namespace 导出(含有子属性的)对象
- export default ES6 默认导出
- export = commonjs 导出模块
- export as namespace UMD 库声明全局变量
- declare global 扩展全局变量
- declare module 扩展模块
- /// 三斜线指令
let b: Boolean = new Boolean;let e: Error = new Error;let d: Date = new Date;let r: RegExp = /[a-z]/;
DOM 和 BOM 的内置对象let body: HTMLElement = document.body;let allDiv: NodeList = document.querySelectorAll;document.addEventListener { // Do something});
其他的都可以参考TS核心库定义文件类型别名字面意思type Name = string;type NameResolver = => string;type NameOrResolver = Name | NameResolver;function getName: Name {if { return n;} else { return n;}}
字符串字面量类型type EventNames = 'click' | 'scroll' | 'mousemove';function handleEvent {// do something}handleEvent, 'scroll'); // 没问题handleEvent, 'dbclick'); // 报错,event 不能为 'dbclick'// index.ts: error TS2345: Argument of type '"dbclick"' is not assignable to parameter of type 'EventNames'.
用来约束当前传递的参数值只能为上面定义的三种一种元组数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象。let tom: [string, number] = ['Tom', 25];let soul1:[Array,number];soul1 = [['age'],18];soul1.pushconsole.log // Array [Array, 18, Array]
接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项。let tom: [string, number];tom = ['Tom', 25];
越界的元素let tom: [string, number];tom = ['Tom', 25];tom.push;tom.push;// Argument of type 'true' is not assignable to parameter of type 'string | number'.
添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型枚举枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。enum soulEnum {sex,name= 'soul',age = 20,ex// extra = "default extra" // 含字符串的枚举不能使用计算属性 所以这一行会报错}// 字符串赋值后 枚举的索引递增不是从0开始了 建议字符串赋值都在后console.log // sexconsole.log // undefinedconsole.log // soul
关键词 - 计算属性 - 递增设置TS-枚举类TS-类这块概念也比较多 就不做搬运工了 有兴趣的可以去看原文// 类class SOUL {public name:string = 'soul' // 共有方法public sayExName:string{ return exName +this.name;} // 共有函数private age:number = 18; // 私有属性 外部无法访问 也无法继承和实例化public readonly sex:string = '男' // 外部只读protected getAge:number{ // 子类可以访问 允许继承 return this.age}}class REALSOUL extends SOUL{constructor{ super console.log); console.log;}}const soulC1 = new REALSOUL;console.log)// 抽象类abstract class JOB{public jobName:string = '前端工程师'public abstract sayJob:string; // 抽象类不能实现此方法 需要子类实现 不能直接实例化抽象类}class SOULJOB extends JOB{constructor{ super}sayJob:string{ return this.jobName}}const souljob1 = new SOULJOB;console.log)
类与接口之前学习过,接口(Interfaces)可以用于对「对象的形状(Shape)」进行描述。这一章主要介绍接口的另一个用途,对类的一部分行为进行抽象。
实现(implements)是面向对象中的一个重要概念。一般来讲,一个类只能继承自另一个类,有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现。这个特性大大提高了面向对象的灵活性。