什么是TypeScipt?
参考文档官方文档
- TypeScript 是由微软开发的一款开源的编程语言。
- TypeScript 是 Javascript 的超集,遵循最新的ES6、Es5 规范。TypeScript 扩展了 JavaScript 的语法。
- TypeScript 更像后端java、C#这样的面向对象语言,可以让 js 开发大型企业项目。
- 谷歌也在大力支持 Typescript 的推广,谷歌的angular2.x+就是基于 Typescript 语法。
- 最新的 Vue 、React 也可以集成 TypeScript。Nodejs 框架 Nestjs、midway 中用的就是 TypeScript 语法。
- 带有类型,是说js在定义变量的时候,类型是动态的,只有在运行的时候才能知道它的具体类型,比如 number或者string,并且类型也是可以动态变化的,而TypeScript则是要求变量有确定的类型,并且在编写代码的时候就已经确定,如果把字符串赋给类型为 number,数字类型的变量,就会出错。
TypeScript安装、编译
安装
npm install -g typescript
或者cnpm install -g typescript
或者yarn global add typescript
运行
tsc helloworld.ts
数据类型
数据类型有两种,分为隐性与显性。
隐性
隐式类型是由 TypeScript 根据变量的值来推断类型,这样的话,代码的写法跟 JS 就一样了,但不同的是它后边不能用其他类型的值来给他重新赋值。
let a = 10;
a = 'hello'; // 自动推断为string类型
显性
var flag: boolean = true;
flag = false;
声明类型的几种语法
/* 第一种写法 *//
var arr: number[] = [1, 2, 3, 4]
console.log(arr);
//* 第二种写法 *//
var arr1: Array<any> = ['20', 4596, true, { a: 1 }]
console.log(arr1);
//* 第三种写法 *//
var arr2: any[] = ['20', 4596, true, { a: 1 }]
console.log(arr2);
元组类型tuple
var arr3: [number, string, boolean] = [123, 'aa', false]
console.log(arr3);
枚举类型(enum)
enum Status { success = 2000, error = 5000 };
var s: Status = Status.success;
console.log(s);
enum Color { blue, red, green }
let c: Color = Color.red;
console.log(c);// 1 如果标识符没有赋值 他的值就是他的下标
枚举例子
// 默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值。
enum Animals { Duck = 1, Monkey, Donkey }
let animal: Animals = Animals.Donkey
console.log('animal', animal);
// 如果我们知道数值是2,但是不确定他映射到Animals里的那个名字,可以这样查找
let animasName: string = Animals[2]
console.log('animasName', animasName); // Monkey
如果给定第一个属性的值为一个常量,其后面的属性值为自增趋势
enum Direction {
Up = 1,
Down,
Left,
Right,
}
// 上面的例子 Up = 1 那Down = 2 ...
enum Direction {
Up,
Down,
Left,
Right,
}
// 上面的例子 Up 没有被指定 那默认为0
访问枚举中的属性
enum Dd {
No,
Yes = 1,
Status,
}
console.log(Dd['Yes']);// 1
console.log(Dd['No']);// 0
console.log(Dd['Status']);// 2
例子
enum E {
X, Y, Z
}
function f(obj: { X: number }) {
return obj.X;
}
// Works, since 'E' has a property named 'X' which is a number.
console.log(f(E));
enum Enum {
A = 1,
B,
C = 2
}
console.log(Enum['B']);// 2
任意类型(any)
var num: any = 123;
num = 'str'
num = true;
console.log(num);
对象类型 object
var obj: object = ['11', 33, 'sdsd']
console.log(obj);
nerver 类型
其他(never类型)数据类型的子类型
var a: never;
console.log(a, 'a');
//返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) { }
}
void类型
typescript中的void表示没有任何类型,一般用于定义方法的时候方法没有返回值。
function run(): void {
console.log('run');
}
run()
function run1(): void {
return 1245 // 报错 定义方法的时候方法没有返回值
}
run1()
组合类型
var num1: number | undefined;
console.log(num ? true : false) // 返回true
console.log(typeof num);
// 组合类型也可以直接使用字面值来定义,这样就规定了一个变量的取值范围
let g: "on" | "off" = "on"
g = "off"
类型别名 type
// 这样代码看起来不太方便,并且这个组合类型只能给 a 使用,如果有一个变量 b 也可以同时是 number 或 string 的类型的话,还要重复定义这个类型。要解决这个问题,我们可以使用 type 关键字来给这个组合类型起个别名,让代码更易读,也方便其他变量使用,这里定义一个 type 名字叫 NumStr,自定义的类型名字推荐首字母大写.
type NumStr = string | number // 给类型组合定义一个别名 (type关键字)
let bb: NumStr = '456456'
console.log(bb, 'bb');
函数 function
// 1 有返回值
function dev(): string {
return '12435' // 正确写法
// return true // 报错
}
dev()
// 2 无返回值
function dev1(): void {
console.log('函数没有返回值');
}
dev1()
// 3 箭头函数
const materials = ['1', '2', '3', '4']
console.log(materials.map((material): any => console.log(materials.length, 'materials.length')))
// 4 定义方法中的传参
function animals(name: string, age: number): string {
return `${name}---${age}`
}
console.log(animals('吉吉国王', 5))
函数重载
函数重载其实就是: 多个函数函数名相同,函数的参数类型,顺序,个数不同。注意函数重载与返回值类型无关。
ts的函数重载比较鸡肋,最终函数逻辑的实现还是在一个函数体内去判断它的参数类型,然后做相应的操作。ts
重载的作用,感觉只是多了一个参数校验的功能。也就是说在进行函数调用的时候,会对参数进行检查,只有传
入的参数类型,顺序,个数与定义的重载函数的参数相同,才能调用成功,否则报错。返回值类型不会进行校验
(函数重载与返回值类型无关)。
let suits = ["hearts", "spades", "clubs", "diamonds"];
function pickCard(x: { suit: string; card: number; }[]): number;
function pickCard(x: number): { suit: string; card: number; };
function pickCard(x): any {
// Check to see if we're working with an object/array
// if so, they gave us the deck and we'll pick the card
if (typeof x == "object") {
let pickedCard = Math.floor(Math.random() * x.length);
// return pickedCard;
return 'pickedCard'; // 并不会报错,编译是通过的
}
// Otherwise just let them pick the card
else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
接口 interface
用来描述对象的内部类型结构
interface Person {
name: string,
age: number,
marry: boolean
}
function getPerson(person: Person): string {
return `hello,m我的名字叫${person.name},今年${person.age}岁了,婚姻状态是${person.marry ? '已婚' : '未婚'}`
}
let result = getPerson({
name: '李磊', age: 18, marry: false
})
console.log(result);
2.接口的继承
interface Animal {
run: boolean;
}
interface Dog extends Animal {
eat: boolean;
}
interface Bird extends Animal {
fly: boolean;
}
let animl = <Dog>{};
animl.run = true
animl.eat = true
console.log(animl);
类 class
class Person {
private ball: string; // 私人有 只能内部访问
protected money: number; // 受保护,只能内部访问
static information: string; // static 不被实例化的属性感觉和private差不多
information: string; //
constructor(public name: string, public age: number, public marry: boolean) {
this.information = `hello,我的名字叫${name},今年${age}岁了,婚姻状态是${marry ? '已婚' : '未婚'}`
}
}
// 实现一个存取器
class Gather {
private _gatherName: string
protected password: number
get gatherName(): string {
return this._gatherName
}
set gatherName(newName: string) {
this._gatherName = newName;
}
}
let oo = new Gather()
console.log(oo);
oo.gatherName = '王五'
console.log(oo);
只读 readonly
let array: number[] = [1, 8, 8, 4, 8]
// ReadonlyArray 指定只读状态,指定之后不可再做修改,否则报错
let role: ReadonlyArray<number> = array
role[0] = 45645 // 报错
//如果想修改内部属性,可以用类型断言重写此变量
array = role as number[];
类类型
个人见解:类类型就是对类class 做了一个约定,也可以叫做约束,体现在入参的类型上。
类类型分为两个部分 1.静态部分 2.实例部分。
interface clockConstructor {
new(hour: number, minute: number);
}
class Clock implements clockConstructor {
currentTime: Date;
constructor(h: number, m: number) { }
}
// 以上这种方式去实现,会出现报错
// 类“Clock”错误实现接口“clockConstructor”。
// 类型“Clock”提供的内容与签名“new (hour: number, minute: number): any”不匹配。ts(2420)
正确写法
interface ClockConstructor {
new(hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick();
}
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) {
console.log('DigitalClock', h, m);
}
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) {
console.log('AnalogClock', h, m);
}
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
digital.tick()
analog.tick()
混合类型
interface Counter {
(start: number): string;
interval: number;
start: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) {
this.start = start
console.log(this.start, 15674532156);
};
counter.interval = 123;
counter.start = 0;
counter.reset = function () {
console.log(this);
console.log('数据重置中···');
this.start = 0
};
return counter;
}
let h = getCounter();
h(10);
h.reset();
console.log(h.start, 'h,start');
h.interval = 5.0;
泛类型
个人见解:不设置类型意为泛类型
function fun1<T>(arg: T[]) {
console.log(arg.length);
}
fun1([1, 2, 4, '2'])
// 在泛型里使用类类型
class BeeKeeper {
hasMask: boolean;
}
class ZooKeeper {
nametag: string;
}
class Animal {
numLegs: number;
}
class Bee extends Animal {
keeper: BeeKeeper;
}
class Lion extends Animal {
keeper: ZooKeeper;
}
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
// let A = createInstance(Lion).keeper.nametag; // 报错
let A = createInstance(Lion).keeper; // undefined
// let B = createInstance(Bee).keeper.hasMask; // 报错
let B = createInstance(Bee).keeper; // undefined
console.log(A,'A');
console.log(B,'B');
End~
未完待续…