TypeScript 1.1 TS简介 TypeScript 是 JavaScript 的强类型版本。然后在编译期去掉类型和特有语法,生成纯粹的 JavaScript 代码。由于最终在浏览器中运行的仍然是 JavaScript,所以 TypeScript 并不依赖于浏览器的支持,也并不会带来兼容性问题。
TypeScript 是 JavaScript 的超集,这意味着他支持所有的 JavaScript 语法。并在此之上对 JavaScript 添加了一些扩展,如 class / interface / module 等。这样会大大提升代码的可阅读性。
和 JavaScript 弱类型不同,TypeScript 这种强类型语言最大的优势在于静态类型检查,可以在代码开发阶段就预知一些低级错误的发生。
一种类似于 JavaScript 的语言,在 JavaScript 的基础之上增加了类型,同时增强了 JavaScript 部分语法功能
遵循 EcmaScript 6 标准规范
由微软开发
Angular 2 框架采用 TypeScript 编写
背后有微软和谷歌两大公司的支持
TypeScript 可以编译成 JavaScript 从而在支持 JavaScript 的环境中运行
TypeScript 和 JavaScript 的关系就好比 less 和 css 的关系
TypeScript 中文网 https://www.tslang.cn/
在线编译环境 https://www.typescriptlang.org/play/index.html
1.2 TS环境搭建
打开命令行,键入npm i -g typescript
全局安装TS
继续在命令行环境下键入 tsc -init
进行初始化, 你会发现根目录下多了 tsconfig.json 的文件,记录了编译成JS的选项
创建ts文件
打开VSCode进入该目录,按下 Ctrl+shift+B 快捷键会进行编译,初次编译会选择编译模式
输入node命令运行js代码
1.3 变量声明 1 2 3 4 5 6 7 8 9 10 11 12 13 var - 作用域 : 全局作用域、函数作用域 - 重复声明 - 变量提升 let - 块级作用域 - 在同一个块中不能重复声明 const - 声明同时必须赋值 - 一旦声明不可改变(对象可以修改) - 块级作用域
1.4 基本数据类型 1 2 3 4 5 6 7 8 var uname :string = "zhangsan" ;let nickname : string = '张三' ;let isDone : boolean = false ;let age : number = 37 ;let sentence : string = `Hello, my nickname is ${ nickname } . I'll be ${ age + 1 } years old next month.`
1 2 3 4 5 6 let list : number [] = [1 , 2 , 3 ];let list : Array <number > = [1 , 2 , 3 ];
1 2 3 4 5 6 7 8 let x : [string, number];x = ['hello' , 10 ]; x = [10 , 'hello' ];
1 2 3 4 5 6 7 8 9 10 - 允许赋任意值 - 但是不能调用任意方法,即便它真的有 let foo : object = { name : 'Jack' , age : 18 }
1 2 3 4 5 6 let notSure : any = 4 ;notSure = "maybe a string instead" ; notSure = false ;
1 2 3 4 5 6 7 8 9 10 function warnUser ( ): void { alert ("This is my warning message" ); } let unusable : void = undefined ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 let u : undefined = undefined ;let n : null = null ;never 是其它类型(包括 null 和 undefined )的子类型,代表从不会出现的值。let x : never ;let y : number ;x = 123 ; x = (()=> { throw new Error ('exception' )})(); y = (()=> { throw new Error ('exception' )})(); function error (message: string ): never { throw new Error (message); } function loop ( ): never { while (true ) {} }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 let someValue : any = true ;let strLength : number = (<string >someValue).length ;let someValue : any = "this is a string" ;let strLength : number = (someValue as string ).length ;
1 2 3 4 5 enum Color {Red , Green , Blue };let c : Color = Color .Blue ;console .log (c);
1.5 解构赋值 1 2 3 4 5 let input = [1 , 2 ];let [first, second] = input;console .log (first); console .log (second);
1 2 3 first = input[0 ]; second = input[1 ];
1 2 [first, second] = [second, first];
1 2 3 4 5 6 7 function ff ([first, second]: [number , number ] ) { console .log (first) console .log (second) } ff ([1 ,2 ])
1 2 3 4 let [first, ...rest] = [1 , 2 , 3 , 4 ]console .log (first) console .log (rest)
1 2 3 let [first] = [1 , 2 , 3 , 4 ];console .log (first);
1 2 let [, second, , fourth] = [1 , 2 , 3 , 4 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let o = { a : "foo" , b : 12 , c : "bar" }; let { a, ...passthrough } = o;let total = passthrough.b + passthrough.c .length ;let { a : newName1, b : newName2 } = o;
1.6 展开操作符 (…)
1 2 3 4 5 6 7 8 let arr1 = [1 , 2 , 3 ];let arr2 = [4 , 5 , 6 ];let arr3 = [...arr1, ...arr2];let obj1 = { a : 1 , b : 2 };let obj2 = { c : 3 }let obj3 = { ...obj1, ...obj2 };console .log (arr3,obj3)
1.7 函数 1 2 3 4 5 6 function add (x: number , y: number ): number { return x + y }
1 2 3 4 function add (x: number , y?: number ): number { return x + 10 }
1 2 3 4 function add (x: number , y: number = 20 ): number { return x + y }
1 2 3 4 5 6 7 8 9 10 function sum (...args: number [] ): number { let ret : number = 0 args.forEach ((item : number ): void => { ret += item }) return ret } sum (1 , 2 , 3 )
1 2 let add = (x : number , y : number ): number => x + y
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function disp (string ):void ; function disp (number ):void ;function disp (n1:number ):void ; function disp (x:number ,y:number ):void ;function disp (n1:number ,s1:string ):void ; function disp (s:string ,n:number ):void ;
1.8 联合类型 1 2 3 4 5 6 7 8 9 10 11 var val :string |number val = 12 val = "Runoob" var arr :number []|string []; var i :number ; arr = [1 ,2 ,4 ] arr = ["Runoob" ,"Google" ,"Taobao" ]
1.9 类 1.9.1 类的基本使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Person { name : string ; age : number ; constructor (name: string , age: number ) { this .name = name; this .age = age; } sayHello ( ) { console .log (this .name ); } } let zs : Person = new Person ('张三' , 18 );
1.8.2 super关键字的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Animal { move (distanceInMeters: number = 0 ) { console .log (`Animal moved ${distanceInMeters} m.` ); } } class Dog extends Animal { bark ( ) { console .log ('Woof! Woof!' ); } } const dog = new Dog ();dog.bark (); dog.move (10 ); dog.bark ();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Animal { name : string ; constructor (theName: string ) { this .name = theName; } move (distanceInMeters: number = 0 ) { console .log (`${this .name} moved ${distanceInMeters} m.` ); } } class Snake extends Animal { constructor (name: string ) { super (name); } move (distanceInMeters = 5 ) { console .log ("Slithering..." ); super .move (distanceInMeters); } } class Horse extends Animal { constructor (name: string ) { super (name); } move (distanceInMeters = 45 ) { console .log ("Galloping..." ); super .move (distanceInMeters); } } let sam = new Snake ("Sammy the Python" );let tom : Animal = new Horse ("Tommy the Palomino" );sam.move (); tom.move (34 ); Slithering ...Sammy the Python moved 5m.Galloping ...Tommy the Palomino moved 34m.
1.9.3 成员修饰符 1 2 3 4 5 6 7 8 9 10 class Animal { public name : string ; public constructor (theName: string ) { this .name = theName; } public move (distanceInMeters: number ) { console .log (`${this .name} moved ${distanceInMeters} m.` ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 - 不能被外部访问,只能在类的内部访问使用 - 私有成员不会被继承 class Person { public name : string ; public age : number = 18 ; private type : string = 'human' public constructor (name :string , age :number ) { this .name = name this .age = age } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 - 和 private 类似,但是可以被继承 class Person { protected name : string ; constructor (name: string ) { this .name = name; } } class Employee extends Person { private department : string ; constructor (name: string , department: string ) { super (name) this .department = department; } public getElevatorPitch ( ) { return `Hello, my name is ${this .name} and I work in ${this .department} .` ; } } let howard = new Employee ("Howard" , "Sales" );console .log (howard.getElevatorPitch ());console .log (howard.name );
1.9.4 getter和setter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Person { private _name :string; constructor (name: string ) { this ._name = name; } set name (value:string ) {this ._name = value;} get name () {return this ._name ;} talk ( ) { alert ("Hi, my name is " + this .name + "!" ); } }
1.9.5 静态成员
不需要实例化访问的成员称之为静态成员,即只能被类访问的成员
static
关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Person { static country = "中国" ; static sayhello ( ) { console .log ("hello" ) } constructor () { } } let p1 = new Person (); let p2 = new Person (); console .log (Person .country ) console .log (p1.country )
1.10 接口 在面向对象编程中,接口是一种规范的定义,它定义了行为和动作规范,起到一种限制和规范的作用。 接口不关心状态数据,也不关心方法的实现细节,它只规定了一些属性和方法,而实现接口的类必须提供具体的信息。
1.10.1 接口对类的规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 interface Human { name : string ; age : number ; say (word : string ): void ; } class Teacher implements Human { name = "老师" ; age = 38 ; say (word : string ): void { console .log ("老师说" +word) } } class Student implements Human { name = "学生" ; age = 18 ; say (word : string ): void { console .log ("学生说" +word) } }
1.10.2 接口对对象的规范 TypeScript 中的接口除了可用于对类的一部分行为进行抽象以外,也常用于对对象的形状(Shape)进行描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 interface Shape { head : string; arm : string; } interface Person { name : string; age : number; shape : Shape ; say (word : string): void ; } let jack : Person = { name : 'Jack' , age : 18 , shape : { head : 'head' , arm : 'arm' }, say (word: string ) { console .log (word) } } jack.say ('hi' )
1.10.3 接口可选属性 接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值了。
1 2 3 4 5 6 7 8 9 interface Person { gender : string , age?: number } let jack : Person = { gender : 'Male' }
1.10.4 接口只读属性 一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly
来指定只读属性:
1 2 3 4 5 6 7 8 9 interface Person { readonly name : string } let jack : Person = { name : 'Jack' } jack.name = 'Ivan'
readonly
vs const
常量使用 const
对象属性使用 readonly
1.10.5 函数接口 因为函数也是对象,所以我们也可以通过接口来对函数做“规定”。
1 2 3 4 5 6 7 8 9 interface Fn { (a : number, b : number): number; } let add : Fn = function (a: number, b: number ): number { return a + b } console .log (add (1 , 2 ))
1.10.6 接口继承 就像 ES6 的 class 一样,接口也可以做继承操作,效果就是会继承父接口的“规定”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 interface Animal { move (): void ; } interface Human extends Animal { name : string; age : number; } let jack : Human = { age : 18 , name : 'Jack' , move ( ) { console .log ('move' ) } }
1.11 命名空间 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 namespace Utils { export interface IPerson { name : string ; age : number ; } } const me : Utils .IPerson = { name : 'funlee' , age : 18 } console .log (me);
1.12 模块 模块是在其自身的作用域里执行,并不是在全局作用域,这意味着定义在模块里面的变量、函数和类等在模块外部是不可见的,除非明确地使用 export 导出它们。类似地,我们必须通过 import 导入其他模块导出的变量、函数、类等。
两个模块之间的关系是通过在文件级别上使用 import 和 export 建立的(其实就是ES6的模块化语法)
1 2 3 4 5 6 7 8 9 10 11 12 export var num = 123 ;export var str = "你好" ;export function say ( ){};var title = "标题" ;export default title;import title,{num,str,say} from './a' console .log (title,str,say)
1.13 声明文件
d.ts为声明文件 主要用作类型的声明
在d.ts使用了declare,表示全局声明类型,需要结合tsconfig.json一起使用才能 有效果。 (使用方式:类似于命名空间)
或者使用export的方式,在普通ts中将d.ts导入(使用方式:类似于模块)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 declare type StringFunc = () => string ;declare namespace API { export interface CurrentUser { avatar?: string ; name?: string ; title?: string ; } }
1.14 例子 写出下列ts代码的含义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 export declare function defineConfig (config: IConfigFromPlugins | IConfig ): IConfigFromPlugins | IConfig ;declare type OverlayFunc = () => React .ReactNode ;export type SiderTheme = 'light' | 'dark' ;const columns : ProColumns <TableListItem >[] = []const LoginMessage : React .FC <{ content : string ; }> = ({ content } ) => () type Env1 = 'prod' | 'test' | 'dev' ;type Env2 = 'prod' | 'boe' | 'ppe' ;type EnvUnion = Env1 | Env2 ; type EnvInter = Env1 & Env2 ; type Partial <T> = { [P in keyof T]?: T[P]; }; type Pick <T, K extends keyof T> = { [P in K]: T[P]; }; type Exclude <T, U> = T extends U ? never : T;type Extract <T, U> = T extends U ? T : never ; type Omit <T, K extends keyof any > = Pick <T, Exclude <keyof T, K>>;declare const REACT_APP_ENV : 'test' | 'dev' | 'pre' | false ;