知乎html
我的博客node
Githubreact
最近入职,发现公司使用到typescript,因此就在此留下一个笔记,方便本身和你们一块儿学习。git
TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个严格超集,并添加了可选的静态类型和基于类的面向对象编程。es6
你们平常学习能够去TS Playground测试一些代码github
那咱们就来开始学习吧!正则表达式
在使用TS以前,咱们定义的JavaScript变量都是弱类型语言,它不像C,Java这种,会在编译的时候对变量进行类型检查,因此有的时候会出现意想不到的Bug。typescript
使用TS咱们能够处理很简单的数据类型:编程
// boolean let isEmpty: boolean = true; // Type '"false"' is not assignable to type 'boolean'. isEmpty = 'false'; isEmpty = false;
// number let num: number = 10; // Type '"1"' is not assignable to type 'number'. num = '1'; num = 1;
// string let github_name: string; github_name = 120; github_name = 'Rain120';
// array let arr: number[]; arr = [1, '2', 3]; arr = [1, 2, 3]; let arr1: Array<number>; arr1 = [1, '2', 3]; arr1 = [1, 2, 3]; let fe: string[]; fe = [1, 2, 3]; // TS fe = ['Vue', 'React', 'Angular'];
// any let type_con: any; type_con = []; type_con = {}; type_con = 1; type_con = '2'; type_con = true; type_con.func();
//void let test_void: void = null; test_void = 1;
function vo(): void { console.log('这是一个返回值为void的函数'); } function vo1(): void { console.log('这是一个返回值为void的函数'); return ''; } function str(): string { console.log('这是一个返回值为string的函数'); } function str1(): string { console.log('这是一个返回值为string的函数'); return 'string'; }
当咱们在使用函数的时候,有些时候会使用到函数参数默认,或者可选参数,那么在TS中如何写呢?json
function game(name: string, rank?: string, score: number = 0): string { return `${name} ${rank} ${score}` } console.log(game('rainy', 'difficult', 10000)); console.log(game('rainy', 'difficult')); console.log(game('rainy'));
class Person { name: string; constructor(name: string) { this.name = name; } greet() { console.log(`Hello, ${this.name}`); } } class Student extends Person { name: string; age: number; constructor(name: string, age: number) { super(name); this.age = age; } greet() { console.log(`Hello, My name is ${this.name} and I'm ${this.age}`); } study() { console.log(`${this.name}, you should go to study.`) } } let p = new Person('Rain120'); console.log('p:', p.name) p.greet() let stu = new Student('Rain', 21); console.log('stu:', stu.name, stu.age); stu.greet(); stu.study();
咱们在学习面向对象的语言,C++和Java时候知道类的属性和方法是有修饰符的,他们决定了外部是否可以访问类中的属性、方法,当用户为定义是,属性和方法默认都是public 属性,其中还有protected 和private 属性。当你使用private 修饰符定义成属性或者方法时,若是你须要让其余使用者使用这个属性时,你能够定义一个public 的方法,以后用户只能经过这个API接口来获取属性值或者方法的结果,例如:
class Person { private name: string; constructor(name: string) { this.name = name; } getName() { return this.name; } } let p = new Person('Rain120'); console.log('person name:', p.name) console.log('person name:', p.getName())
虽然这里报错了,可是编译结果倒是能够的应为TS在转换成JS语言后,并无真的将name编译成私有的属性,TypeScript的核心原则之一是对值所具备的结构进行类型检查,它的做用只是提示开发者。
protected 修饰符与private 修饰符的行为很类似,但有一点不一样,protected 成员在派生类中仍然能够访问, 这就不详细讲解这些了,你们能够去学习下Java或者C++的类,感觉一下。
在TypeScript里,接口的做用就是为这些类型命名和为你的代码或第三方代码定义契约。这句话太官方了,我本身理解的就是它定义了一些你本身约定的参数类型。
工做中,咱们使用到的是React+Typescript,因此,我把我平常写法拿出来。
interface SystemsProps { systems: any } export class Systems extends React.Component<SystemsProps, any> ... render() { const { systems } = this.props return ( <div>{systems.name}</div> ) } }
固然,从C++中学到接口也是能够继承的,例如:
interface Color{ color: string; } interface Car extends Color{ price: number; } let car = <Car>{}; car.color = "white"; car.price = 10000000;
在像C++和Java这样的语言中,可使用泛型来建立可重用的组件,一个组件能够支持多种类型的数据。 这样用户就能够以本身的数据类型来使用组件。
其实咱们以前有用到泛型,只是没有说到这个概念。
let arr: Array<number> = [1, 2, 3, 4];
这是一个最简答你的泛型,定义了一个number类型的数组,下面我写一个复杂点的泛型:
class Fruit { name: string; price: number; constructor(name: string, price: number) { this.name = name; this.price = price; } sold() { console.log(`${this.name} sold $${this.price}`) } } let fruit: Array<Fruit> = [] fruit[0] = new Fruit('apple', 8) fruit[1] = new Fruit('banana', 5) fruit[2] = new Fruit('lemon', 10) console.log(fruit)
这个泛型是一个Fruit类型的数组,这个数组的子元素全是Fruit类型,当咱们定义一个其余类型是,例如
fruit[3] = { name: 'watermelon', price: 2 }
let num = 10; num = 'str';
咱们日常在使用变量赋值的时候,这样写是没有问题,可是使用TS类型检查后,它会根据用户第一次定义或者赋值的类型来推断该变量的类型,这就是TS的类型推断机制。
这里咱们讲下咱们常见的几种的迭代器,包括for-in, for-of,用来跟forEach对比,直接上代码,咱们从代码来分析它们之间的不一样
let arr: any = ['a','b','c']; arr.type = 'array' arr.forEach((item, index) => { console.log('forEach', index, item, arr[index]); }) for (let i in arr) { console.log('for-in', i, arr[i]); } let obj = { 'a': 'I\'m a', 'b': 'I\'m b', 'c': 'I\'m c' } for (let i of arr) { console.log('for-of', i, obj[i]); }
从结果上来看,
forEach:只是常见的for循环,它不会遍历该对象的属性值;
for-in:迭代的是对象的键(key)的列表,它会遍历对象的属性;
for-of:迭代对象的键对应的值(value),它也不会遍历对象的属性。
这个地方熟悉CommonJS的都会知道export(导出), import(导入),因此这里就不详细讲了,直接跳过
最后讲一下,tsconfig.json的配置,详见tsconfig.json
{ "compilerOptions": { "moduleResolution": "node", "outDir": ./dist", // 生成的全部文件放在dist目录下 "target": "es5", // 将JavaScript代码降级到低版本ECMAScript 5 "lib": ["es6", "dom"], "rootDir": "app/", //仅用来控制输出的目录结构。 "jsx": "react", // 用于指定按照何种方式生成jsx代码,可选react和preserve。 "module": "esnext", // 用于指定模块的代码生成规则,可使用 commonjs 、 amd 、 umd 、 system 、 es6 、 es2015 、 none 这些选项。 "declaration": false, // 是否须要生成定义文件d.ts,设置为true,则生成 "allowJs": true, // 接受JavaScript作为输入 "allowSyntheticDefaultImports": true, // 置为true时,则容许从没有默认导出的模块中默认导入(也就是不作检查)。 "inlineSourceMap": false, // 是否须要将sourceMap文件生成到js文件中,设置为true,则生成到js文件中。 "sourceMap": true, // 把 ts 文件编译成 js 文件的时候,同时生成对应的 map 文件 "noEmitOnError": false, // 设置为true时,若是遇到了错误,就再也不输出 "emitDecoratorMetadata": false, // 设置为true,则使用元数据特性 "experimentalDecorators": true, // 设置为true,则支持ES7的装饰器特性 "noImplicitReturns": true, // 会防止你忘记在函数末尾返回值 "noImplicitThis": false, "noImplicitUseStrict": false, // 当设置为true时,编译输出时不会调用'use strict'指令(也就是不生成use strict) "noImplicitAny": false, // 若是编译器没法根据变量的用途推断出变量的类型,它就会悄悄的把变量类型默认为 any。 "noUnusedLocals": false, "baseUrl": "app", "paths": { "app": ["app"] } }, // 包括app下的全部.ts(对应js文件), .tsx(对应jsx文件)文件 "include": [ "app/**/*.ts", "app/**/*.tsx" ], // 忽略node_modules下全部的文件 "exclude": [ "node_modules", ... //其余要忽略的文件或者正则表达式表示 ] }