共计 6231 个字符,预计需要花费 16 分钟才能阅读完成。
TS 介绍
TS 是什么
ts 是领有类型查看零碎的 javascript 超集, 提供了对 es6 的反对, 能够编译成纯 javascript, 运行在任何浏览器上。
TypeScript 编译工具能够运行在任何服务器和任何零碎上。TypeScript 是开源的。
为什么要用 TS
ts 总体给我的感觉就是, 它能束缚代码, 又有肯定的灵便度, 能够造就你的编程习惯, 输入更高质量, 维护性高, 可读性高的代码
- 编译代码时, 进行严格的动态类型查看, 编译阶段而不是运行时发现很多谬误, 特地是一些很低级的谬误
- 帮忙咱们在写代码的时候提供更丰盛的语法提醒, 不便的查看定义对象上的属性和办法
比方: 你给函数传了一个对象, 你在函数实现的时候还得记住对象外面都有啥参数, 你定义的参数名字是啥
TS 装置
npm init -y
npm install typescript -g
数据类型
- js 中的数据类型:
字符串(String)、数字 (Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
对象(Object)、数组(Array)、函数(Function) - ts 蕴含 js 中所有的类型, 而且还新增了几种类型
void、any、never、元组、枚举、高级类型
类型注解:
(变量 / 函数):type
-
布尔类型(boolean)
let flag: boolean = true
-
数字类型(number)
let num: number = 8;
-
字符串类型(string)
let str: string = 'sxh';
- 数组类型(array)
-
let arr1:number[]=[1,2,3] let arr2:Array<number>=[1,2,3]
只读数组 数组创立后不能被批改
let ro: ReadonlyArray<number> = arr1; // arr1.push(3); // ro[1] = 4; // ro.push(6); // ro.length = 100; // arr1 = ro; // let arr3: number[] = ro
-
元组类型 (tuple)
管制了数组成员的类型和数量let tuple:[string,number]=['sxh',10] // 元祖越界问题:tuple.push(2)// 能够增加的类型是所有数组成员的联结类型 console.log(tuple[2])// 不能这样拜访
-
枚举类型 (enum)
一般枚举
若枚举类型未指定值或指定的值为 number 类型, 可对其进行双向取值// 双向取值 enum Color { RED, BLUE, } console.log(Color[0], Color[1]); console.log(Color['RED'], Color['BLUE']); enum Color { RED=2, BLUE, } enum ActionType { ADD = 'ADD', EDIT = 'EDIT', DELETE = 'DELETE', }
常量枚举
const enum Status { 'success', 'warning', 'fail', } let loginStatus = [Status.success, Status.warning, Status.fail];
keyof typeof Enum, 将枚举类型转换为联结类型
enum ActionType { ADD, EDIT, DELETE, } type ActionTypeConst = keyof typeof ActionType // 'ADD' | 'EDIT' | 'DELETE'
-
null、undefined
null, undefined 是其余类型的子类型, 能够赋值给其余类型的变量
strictNullChecks 为 true 的话不能赋值给其余类型let str: string; str = null; str = undefined;
- 任意类型 (any)
任意类型 any 类型 类型转换艰难的时候, 数据类型结构复杂, 没有类型申明的时候用
如果变量定义为 any 类型, 跟 js 差不多了, 不进行类型查看了 -
unkonwn 未知类型
let a: any let b: unkonwn a.toFixed() b.toFixed()
-
void 无类型
罕用于没有具体返回值的函数const handler = (param: string):void => {}
-
never 类型
永远不存在的值
任何类型的字类型, 能够赋值给任何类型
然而任何类型都不可赋值给 never, 包含 anyfunction error(msg: string): never {throw new Error('我报错了'); // 间接异样完结了 } function loop(): never {while (true) {}} function fn(x: number | string) {if (typeof x === 'number') { // 类型爱护 console.log(x); } else if (typeof x === 'string') {console.log(x); } else {console.log(x); } }
类型推论
如果没有指定类型, TS 会依据类型推论推断出一个类型.
如果变量定义的时候没有赋值, 默认是 any 类型
let x; // 能够赋值为任何类型的值
let x1 = '生生世世'; // x1 会推论成 sring 类型, 不能给 x1 赋值为其余类型了
// x1 = 222;
如果 TS 能正确推断出其类型, 咱们可采纳类型推论而不用定义类型
function sum(x: number, y: number){return x + y;}
联结类型
let name1: string | number;
// console.log(name1.toFixed());
// console.log(name1.toString());
name1 = 3;
name1 = 'sxh';
类型断言
类型断言用来通知编译器“我晓得本人在干什么”, 有 尖括号 和 as 两种写法. 在 tsx 语法中, 只反对 as.
let name1: string = '111'
let name2: string | number;
// console.log(name2.toFixed())
console.log((name2 as number).toFixed());
// 双重断言
console.log((name1 as any) as boolean);
字符串字面量类型
// 字符串字面量
const left: 'left' = 'left';
const right: 'right' = 'right';
type pos = 'left' | 'right';
function loc(pos: pos) {}
// loc('up')
// 类型字面量
type Person = {
name: string;
age: number;
};
let p1: Person = {
name: 'sxh',
age: 18,
};
字符串字面量 vs 联结类型
type T1 = '1' | '2' | '3';
type T2 = string | number | boolean;
let t1: T1 = '2';
let t2: T2 = true;
函数
函数定义
定义函数有两种形式: 1. 函数定义 2. 函数表达式
// 1. 间接申明
function person2(name: string): void {console.log(name);
}
person2('sxh');
// 2. 变量申明
let sum: (x:number, y:number) => number
sum = (a,b)=>a+b
sum(1,2)
// 3. 类型别名
type Sum = (a: number, b: number) => void;
let sum: Sum = function (a: number, b: number): number {return a + b;};
let sum2: Sum = function (a: number, b: number): void {// 没有返回值
// return a + b;
};
const myAdd = (x: number, y: number) => x + y; // 也能够间接这样定义, 类型会主动推导
// 4. 接口
interface Sum{(x:number, y: number):number
}
let sum: Sum = (a,b)=>a+b
sum(1,2)
可选参数
必须放在最初一个参数地位
function sum3(a: number, b: number, c?: number) {}
sum3(1, 2);
// 设置默认值, 最初一个参数设置默认值就, 函数调用可传可不传, 相当于可选参数
function sum4(a: number, b: number, c = 6) {return a + b + c;}
sum4(1, 2);
// 第一个参数设置默认值, 应用默认调用的时候必须传 undefiend
function sum5(a = 3, b: number) {return a + b;}
console.log(sum5(undefined, 2));
残余参数
function sum6(...args: number[]) {return args.reduce((val, item) => val + item, 0);
}
sum6(1, 2, 3, 5);
函数的重载
给同一个函数提供多个函数定义
let catOpt: any = {};
function cat(param: string): void;
function cat(param: number): void;
function cat(param: any) {if (typeof param === 'string') {catOpt.name = param;} else if (typeof param === 'number') {catOpt.age = param;}
}
cat('小花');
cat(3);
function add(a: string, b: number): void;
function add(a: number, b: number): void;
function add(a: string | number, b: string | number): void {}
add(1, 2);
// add(1, '2');
类
如何定义类
class Book {
name: string;
getName(): void {console.log(this.name);
}
}
let book1 = new Book();
book1.name = 'ts';
book1.getName();
存取器
通过存取器来扭转一个类中属性的读取和赋值行为
class MyBook {
bname: string; // 属性
constructor(bname: string) {this.bname = bname;}
get name() {return this.bname;}
set name(value) {this.bname = value;}
}
let myBook = new MyBook('ts');
myBook.name = 'js';
console.log(myBook.name);
参数属性
class MyBook1 {
// bname: string;
constructor(public bname: string) {// this.bname = bname;}
get name() {return this.bname;}
set name(value) {this.bname = value;}
}
let myBook1 = new MyBook1('ts');
myBook1.name = 'js';
console.log(myBook1.name);
readonly
class MyBook2 {
readonly bname: string; // 公开的只读属性只能在申明时或者构造函数中赋值
readonly num: number = 1;
constructor(bname: string) {this.bname = name;}
changeName(value) {// this.bname = value;}
}
继承
class Animal {
name: string;
constructor(name: string) {this.name = name;}
eat(food: string) {console.log('吃什么', food);
}
}
class Cat extends Animal {
color: string;
constructor(name: string, color: string) {super(name);
this.color = color;
}
}
let cat = new Cat('哈哈', 'white');
console.log(cat.name);
cat.eat('fish');
类外面的修饰符
public 私有属性, private 公有属性, protected 受爱护的
// public 私有属性 , ts 默认为 public
class Animal1 {
public name: string; // 本人, 子类和实例都能够拜访
private age: number = 2; // 本人能够拜访, 子类 和 实例 都不能够拜访,
protected body: string; // 本人和子类能够拜访, 实例不能够拜访
public constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public eat(food: string) {console.log('吃什么', food);
}
private getAge() {return this.age;}
}
class Dog extends Animal1 {
color: string;
constructor(name: string, age: number, color: string) {super(name, age);
this.color = color;
}
dogInfo() {// console.log(this.name);
// console.log(this.body);
// console.log(this.age);
}
}
let an = new Animal1('哈哈', 2);
let dog = new Dog('哈哈', 2, 'white');
console.log(dog.name);
// console.log(dog.age);
// console.log(dog.body);
// console.log(dog.getAge());
动态属性 静态方法
类本身上的属性和办法
class Button {
static type = 'link';
static getType() {return Button.type;}
public content: string;
constructor(content: string) {this.content = content;}
}
console.log(Button.getType);
console.log(Button.type);
class SubButton extends Button {}
let btn = new SubButton('ok');
SubButton.type = 'e';
console.log(Button.type);
console.log(SubButton.type);
抽象类
是抽象概念, 不能被实例化
abstract class Input {
label: string;
abstract changeValue(): void; // 此办法在子类中必须得实现}
class SearchInput extends Input {changeValue() {} // 必须得实现抽象类里形象办法}
形象办法 不蕴含具体实现, 必须在子类中实现
有关键字 abstract
接口