TypeScript
TypeScript 进阶
类型别名 类型别名用来给一个类型起个新名字,类型别名常用于联合类型 字符串字面量类型 字符串字面量类型用来约束取值只能是某几个字符串中的一个 元组 数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象 当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项 当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型 ` 枚举 类型用于取值被限定在一定范围内…
类型别名 类型别名用来给一个类型起个新名字,类型别名常用于联合类型 字符串字面量类型 字符串字面量类型用来约束取值只能是某几个字符串中的一个 元组 数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象 当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项 当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型 ` 枚举 类型用于取值被限定在一定范围内…
类型别名用来给一个类型起个新名字,类型别名常用于联合类型
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n;
} else {
n();
return n();
}
}
字符串字面量类型用来约束取值只能是某几个字符串中的一个
type EventNames = 'click' | 'scroll' | 'mousemove';
function Handle(ele: Element, event: EventNames): number {
return 1;
}
Handle(document.getElementById('box'), 'click');
数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象
let tuple: [string, number] = ['hello', 12];
let tuple2: [string, number];
tuple2[0] = 'hello';
当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项
当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型 `
let tuple: [string, number] = ['hello', 12];
tuple.push('world');
tuple.push(12);
类型用于取值被限定在一定范围内的场景
enum Days {
Sun,
Mon,
Tue,
Wed,
Thu,
Fri,
Sat
}
console.log(Days['Sun'] == 0);
console.log(Days[0] == 'Sun');
// 手动赋值
// 不要出现覆盖现象,因为覆盖ts是无法察觉到的,
// 比如下例中Sun=2,Tue已经是2了,那么编译出来Days['Tue'] == 2 , Days['Sun'] == 2
// 但是Days[2] == 'Tue',Day[2]!='Sun'
enum Days {
Sun = 7,
Mon = 1,
Tue,
Wed,
Thu,
Fri,
Sat
}
console.log(Days['Sun'] == 7);
console.log(Days['Tue'] == 2);
// 常数项分类:https://ts.xcatliu.com/advanced/enum#chang-shu-xiang-he-ji-suan-suo-de-xiang
enum Color {
Red,
Blue = 'blue'.length
}
// 如果紧接在计算所得项后面的是未手动赋值的项,那么就会因为无法获取初始化而报错
// 报错
enum Color2 {
Blue = 'blue'.length,
Red
}
// 不报错
enum Color3 {
Blue = 'blue'.length,
Red = 1.5
}
const enum Direction {
Up,
Down,
Left,
Right
}
let direction = [Direction.Up, Direction.Down, Direction.Left, Direction.Right];
// declare 定义的类型只会用于编译时的检查,编译结果中会被删除
// 外部枚举与声明语句一样,常出现在声明文件中
// declare 和 const可以共用
declare enum Direction1 {
Up,
Down,
Left,
Right
}
declare const enum Direction2 {
Up,
Down,
Left,
Right
}
let direction1 = [Direction1.Up, Direction1.Down, Direction1.Left, Direction1.Right];
let direction2 = [Direction2.Up, Direction2.Down, Direction2.Left, Direction2.Right];
生成的 js
var direction1 = [Direction1.Up, Direction1.Down, Direction1.Left, Direction1.Right];
var direction2 = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
TypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。
class Animal {
public name;
public constructor(name) {
this.name = name;
}
}
let a = new Animal('dog');
a.name = 'cat';
class Animal {
private name;
public constructor(name) {
this.name = name;
}
}
let a = new Animal('dog');
// 报错
a.name = 'cat';
class Animal {
private name;
protected age;
public constructor(name) {
this.name = name;
}
}
class Person extends Animal {
public constructor(name) {
super(name);
}
public getAge() {
console.log(this.age);
}
// 报错
public getName() {
console.log(this.name);
}
}
// 首先,抽象类是不允许被实例化的:
abstract class Animal {
public name: string;
public constructor(name: string) {
this.name = name;
}
}
class Person extends Animal {
public constructor(name: string) {
super(name);
}
getName(): string {
console.log(this.name);
return this.name;
}
}
// 报错
// let a = new Animal()
// 不报错
let p = new Person('dog');
console.log(p.name);
生成的 js
var __extends =
(this && this.__extends) ||
(function() {
var extendStatics = function(d, b) {
extendStatics =
Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array &&
function(d, b) {
d.__proto__ = b;
}) ||
function(d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
};
return extendStatics(d, b);
};
return function(d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __());
};
})();
// abstract 用于定义抽象类和其中的抽象方法。
// 首先,抽象类是不允许被实例化的:
var Animal = /** @class */ (function() {
function Animal(name) {
this.name = name;
}
return Animal;
})();
var Person = /** @class */ (function(_super) {
__extends(Person, _super);
function Person(name) {
return _super.call(this, name) || this;
}
Person.prototype.getName = function() {
console.log(this.name);
return this.name;
};
return Person;
})(Animal);
// 报错
// let a = new Animal()
// 不报错
var p = new Person('dog');
console.log(p.name);
接口(Interfaces)可以用于对「对象的形状(Shape)」进行描述。接口还可以对类的一部分行为进行抽象
// 不同类之前可以有一些公有的特性,把这些公有的提成接口,用implements来实现
// 门是一个类,防盗门是门的子类,防盗门有报警,防盗门有开灯关灯
// 车是一个类,小卡车是车的子类,小卡车有报警,小卡车有开灯关灯
// 车是一个类,大卡车是车的子类,大卡车有报警,大卡车没有开灯关灯,大卡车的报警为吹笛子
// 把报警和灯提取出来,作为一个接口
// 报警接口
interface Alarm {
alert();
}
// 开关灯接口
interface Light {
lightOn();
lightOff();
}
// 笛子接口
interface Flute extends Alarm {
boast();
}
class Door {}
// 防盗门
class SecurityDoor extends Door implements Alarm, Light {
alert() {
console.log('防盗门报警');
}
lightOn() {
console.log('防盗门选择开灯');
}
lightOff() {
console.log('防盗门选择关灯');
}
}
class Car {}
// 小卡车
class SmallCar extends Car implements Alarm, Light {
alert() {
console.log('小卡车报警');
}
lightOff() {
console.log('小卡车选择关灯');
}
lightOn() {
console.log('小卡车选择开灯');
}
}
// 大卡车
class BigCar extends Car implements Flute {
alert() {}
boast() {}
}
生成的 js
var __extends =
(this && this.__extends) ||
(function() {
var extendStatics = function(d, b) {
extendStatics =
Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array &&
function(d, b) {
d.__proto__ = b;
}) ||
function(d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
};
return extendStatics(d, b);
};
return function(d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __());
};
})();
var Door = /** @class */ (function() {
function Door() {}
return Door;
})();
// 防盗门
var SecurityDoor = /** @class */ (function(_super) {
__extends(SecurityDoor, _super);
function SecurityDoor() {
return (_super !== null && _super.apply(this, arguments)) || this;
}
SecurityDoor.prototype.alert = function() {
console.log('防盗门报警');
};
SecurityDoor.prototype.lightOn = function() {
console.log('防盗门选择开灯');
};
SecurityDoor.prototype.lightOff = function() {
console.log('防盗门选择关灯');
};
return SecurityDoor;
})(Door);
var Car = /** @class */ (function() {
function Car() {}
return Car;
})();
// 小卡车
var SmallCar = /** @class */ (function(_super) {
__extends(SmallCar, _super);
function SmallCar() {
return (_super !== null && _super.apply(this, arguments)) || this;
}
SmallCar.prototype.alert = function() {
console.log('小卡车报警');
};
SmallCar.prototype.lightOff = function() {
console.log('小卡车选择关灯');
};
SmallCar.prototype.lightOn = function() {
console.log('小卡车选择开灯');
};
return SmallCar;
})(Car);
// 大卡车
var BigCar = /** @class */ (function(_super) {
__extends(BigCar, _super);
function BigCar() {
return (_super !== null && _super.apply(this, arguments)) || this;
}
BigCar.prototype.alert = function() {};
BigCar.prototype.boast = function() {};
return BigCar;
})(Car);
class Ponit {
x: number;
y: boolean;
}
interface Ponit3d extends Ponit {
z: string;
}
let Ponit3d: Ponit3d = { x: 1, y: false, z: 'hello' };
// 接口来定义函数的形状
interface Couter {
(start: number): string;
interval: number;
reset(): void;
}
function getCouter(): Couter {
let couter = <Couter>function(strat: number) {};
couter.interval = 1000;
couter.reset = function() {};
return couter;
}
let g = getCouter();
g(10);
g.reset();
g.interval = 2000;
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
// 没有准确的定义返回值的类型,预期数组中的每一项的类型与输入的value的类型一致
function createArray(length: number, value: any): Array<any> {
let result = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray(3, 'x');
function createArray<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray<String>(3, 'x');
// 定义了一个swap函数,用来交还输入的元祖
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
swap<string, number>(['hello', 12]);
// 在函数内部使用泛型的时候,事先不知道它是哪种类型,所以不能随意操作它的属性与方法
// 报错
// function login<T>(name: T): T {
// console.log(name.length);
// return name;
// }
// 进行泛型约束:只允许传入有length属性的变量
interface Lenghtwise {
length: number;
}
function login2<T extends Lenghtwise>(name: T): T {
console.log(name.length);
return name;
}
// 报错:因为1没有长度
// login2(1);
// 不报错
login2('hello');
// 多个类型参数之前也可以互相约束
// T继承于U,保证了U上不会出现T中不存在的字段
function copy<T extends U, U>(target: T, source: U): T {
for (let key in source) {
target[key] = (<T>source)[key];
}
return target;
}
let x = { a: 1, b: 2 };
// 报错
// copy(x, { a: 10, b: '20' });
// 不报错
copy(x, { a: 10, b: 20 });
interface CreateFn {
<T>(length: number, value: T): Array<T>;
}
let createFn: CreateFn = function<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
};
createFn(3, 'x');
interface CreateFn2<T> {
(length: number, value: T): Array<T>;
}
let createFn2: CreateFn2<number> = function<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
};
createFn2(3, 1);
// 泛型参数可以选择默认值
class Class1<T = string> {
get: T;
add: (x: T, Y: T) => T;
}
let class1 = new Class1();
class1.get = 0 + '';
class1.add = (x, y) => x + y;
如果定义了两个相同名字的函数、接口或类,那么它们会合并成一个类型
function reverse(x: number): number;
function reverse(X: string): string;
function reverse(x: number | string): number | string {
if (typeof x == 'number') {
return Number(
x
.toString()
.split('')
.reverse()
.join('')
);
} else {
x.split('')
.reverse()
.join('');
}
}
// 合并的属性的类型必须是唯一的
interface Car {
price: number;
}
interface Car {
age: string;
}
// 相当于
// interface Car {
// price: number;
// weight: number;
// }
interface Bike {
price: number;
alert(a: string): string;
}
interface Bike {
name: string;
alert(a: string, b: number): number;
}
// 相当于
// interface Bike {
// price: number;
// name: string;
// alert(a: string): string;
// alert(a: string, b: number): number;
// }
暂无评论
确认操作
请再次确认编辑图片
待上传图片 (剩余 0 张)
项目详情
确认评论邮箱
邀请制评论