各种各样的类型
基础类型: number string null undefined symbol boolean void空
对象类型: {} Class function []
const teacher: {
name: string;
age: number;
} = {
name: "Dell",
age: 18
};
const numbers: number[] = [1, 2, 3];
class Person {}
const my: Person = new Person();
const getNumber: () => number = () => {
return 123;
};
枚举类: 对应的值默认从0开始 可以手动赋值
enum Status {
OFFLINE,
ONLINE,
DELETED
}
console.log(Status.OFFLINE);
console.log(Status[0]);
function getResult(status) {
if (status === Status.OFFLINE) {
return "offline";
} else if (status === Status.ONLINE) {
return "online";
} else if (status === Status.DELETED) {
return "deleted";
} else {
return "error";
}
}
let result = getResult(Status.OFFLINE);
console.log(result);
never: 永远不会执行完函数
function errorEmitter(): never {
throw new Error();
}
function whileEmitter(): never {
while (true) {}
}
数组:
const numberArr: number[] = [1, 2, 3];
const arr: (number | string)[] = [1, "2", "3"];
const objectArr: { name: string }[] = [{ name: "1" }, { name: "2" }];
元组:
const teacherInfo: [string, string, number] = ["yh", "nv", 10];
const teacherList: [string, number][] = [
["yh", 10],
["hy", 20]
];
type alias 类型别名:
type User = { name: string; age: number };
const objArr: User[] = [
{ name: "1", age: 10 },
{ name: "2", age: 11 }
];
class Teacher {
name: string;
age: number;
}
const objArr1: Teacher[] = [
new Teacher(),
{
name: "h",
age: 10
}
];
type annotation 类型注解 我们来告诉ts变量类型
type inference 类型推断 ts自动尝试分析变量类型
接口、类、继承
接口:
interface Person {
//readonly name: string; //修饰符只读不能赋值
name: string;
age?: number; //加一个?表示可有可无
[propName: string]: any; //可以传 名字为字符串 值为任何类型
//say(): string;
}
const getName = (person: Person) => {
console.log(person.name);
};
getName({ name: "yh" });
class Users implements Person {
//在类里用接口
name = "yh";
// say() {
// return "hello";
// }
}
interface Study extends Person {
//接口继承
// hight: string;
}
类继承:
class Persons {
name: string = "yh";
getName() {
return this.name;
}
}
//类继承 Teachers是子类 Persons是父类
class Teachers extends Persons {
getTeacherName() {
return "teacher";
}
getName() {
//super.getName(); 调用父类方法
return super.getName() + "覆盖父类getName方法";
}
}
const person = new Persons();
console.log(person.getName()); //直接运行ts代码 ts-node type2.ts
const teacher = new Teachers();
console.log(teacher.getName());
访问类型: private允许在类内调用 protected允许在类内及继承的子类中使用 public允许在类的内外调用
public name: string;
//private name: string;
//protected name:string;
sayHi() {
console.log("111");
}
}
类构造器: constructor
class Person3 {
// public name: string;
// constructor(name: string) {
// this.name = name;
// }
constructor(public name: string) {}
}
const person3 = new Person3("yh");
console.log(person3.name);
class Teacher3 extends Person3 {
constructor(age: number) {
super("yh"); //子类用构造器需调用父类构造器
}
}
const teacher3 = new Teacher3(28);
get set:
class Person4 {
constructor(private _name: string) {}
get name() {
return this._name;
}
set name(name: string) {
this._name = name;
}
}
const person4 = new Person4("yh");
console.log(person4.name);
person4.name = "yh"; //赋值
构建一个单例:
class Demo {
private static instance: Demo;
private constructor() {}
static getInstance() {
if (!this.instance) {
this.instance = new Demo();
}
return this.instance;
}
}
const demo1 = Demo.getInstance();
抽象类: 抽象方法 把公用的东西抽象出来
abstract class Geom {
width: number;
getType() {
return "Geom";
}
abstract getArea(): number;
}
class Circle extends Geom {
getArea() {
return 123;
}
}
class Square extends Geom {
getArea() {
return 456;
}
}
抽象接口:
interface Person6 {
name: string;
}
interface teacher6 extends Person6 {}
interface stydent extends Person6 {
age: number;
}
const teacher6 = {
name: "yh"
};
const stydent = {
name: "hy",
age: 18
};
const getUserInfo = (user: Person6) => {
console.log(user.name);
};
getUserInfo(stydent);
联合类型+类型保护
联合类型:
interface Bird {
fly: boolean;
sing: () => {};
}
interface Dog {
fly: boolean;
bark: () => {};
}
类型保护:
//类型断言方式 as语法
function canDo(animal: Bird | Dog) {
if (animal.fly) {
(animal as Bird).sing();
} else {
(animal as Dog).bark();
}
}
//in 语法
function cantDo(animal: Bird | Dog) {
if ("sing" in animal) {
animal.sing();
} else {
animal.bark();
}
}
//typeof 语法
function add(first: string | number, second: string | number) {
if (typeof first === "string" || typeof second === "string") {
return `${first}${second}`;
}
return first + second;
}
//instanceof 语法 不能用interface
class NumberObj {
count: number;
}
function addSecond(first: object | NumberObj, second: object | NumberObj) {
if (first instanceof NumberObj && second instanceof NumberObj) {
return first.count + second.count;
} else {
return 0;
}
}
泛型
泛型是指—–generic 泛指的类型 调用时指定类型
function join<T>(first: T, second: T): T {
return first;
}
join<string>("1", "123");
数组泛型 T[]
function map<T>(params: Array<T>) {
return params;
}
map<string>(["123"]);
多个泛型
function add<T, P>(first: T, second: P) {
return `${first}+${second}`;
}
add<number, string>(1, "11");
类中泛型
class DataManager<T> {
constructor(private data: T[]) {}
getItem(index: number): T {
return this.data[index];
}
}
const data = new DataManager<number>([1, 2]);
data.getItem(0);
泛型继承
interface Item {
name: string;
}
class DataManager1<T extends Item> {
constructor(private data: T[]) {}
getItem(index: number): string {
return this.data[index].name;
}
}
const data1 = new DataManager1([{ name: "dd" }]);
使用泛型作为一个具体的类型注解
const funcs: <T>() => string = <T>() => {
return "123";
};
function hello<T>(param: T) {
return param;
}
const func: <T>(param: T) => T = hello;
泛型中使用keyof语法
interface Person {
name: string;
age: number;
}
class Teacher {
constructor(private info: Person) {}
//循环Person -> T的类型为string ->返回类型为T的类型
getInfo<T extends keyof Person>(key: T): Person[T] {
return this.info[key];
}
}
const teacher = new Teacher({
name: "dell",
age: 18
});
const test = teacher.getInfo("name");
console.log(test);
namespace命名空间
在ts中初步的模块化思想就是namespace(命名空间)
//编译后只生成一个变量
namespace Home {
class Header {
constructor() {
const elem = document.createElement("div");
elem.innerText = "Header";
document.body.appendChild(elem);
}
}
class Content {
constructor() {
const elem = document.createElement("div");
elem.innerText = "Content";
document.body.appendChild(elem);
}
}
//只暴露这一个类
export class Page {
constructor() {
new Header();
new Content();
}
}
//定义接口
export interface Uset{
name:string
}
//定义子空间
export namespace childHome Uset{
export class Test{}
}
}
两个ts文件中命名空间相互引用时,会使用依赖声明来标注
声明方式:///<reference path=’./components.ts’/>
.d.ts注解文件
ts里有一种独特的文件,以.d.ts结尾,这种文件叫做类型描述文件。注解文件通常使用declare关键字描述类型
这里以jquery为例,现在想在ts文件种使用jq的方法,如下:
//import $ from "jquery"; //es6引入jq模块包 这里的引用名字和注解文件里的名字要相同
$(function() {
$("body").html("123");
new $.fn.init();
});
这时需要创建一个jquery.d.ts文件帮助ts理解jq,分为两种情况,外部引入jq和Es6引入jq模块包
第一种 (外部引入jq.js文件)
函数重载:声明 -> $的类型是函数,接收函数,返回值是空
interface JqueryInstance {
html: (html: string) => {};
}
declare function $(readyFunc: () => void): void;
declare function $(selector: string): JqueryInstance;
//对类和对象进行类型定义,命名空间嵌套
declare namespace $ {
namespace fn {
class init {}
}
}
interface的方式实现函数重载
interface JQuery {
(readyFunc: () => void): void;
(selector: string): JqueryInstance;
}
declare var $: JQuery;
第二种(Es6引入jq模块包)
Es6模块化必须要添加注解 module后的名字和引用的名字一样
declare module "jquery" {
interface JqueryInstance {
html: (html: string) => {};
}
//混合类型
function $(readyFunc: () => void): void;
function $(selector: string): JqueryInstance;
namespace $ {
namespace fn {
class init {}
}
}
export = $;
}
奇奇怪怪的装饰器
学习准备:装饰器是实验性特性,未来可能会不是这种用法
现在想要使用需要在tsconfig.json文件中打开这两个注释,否则使用装饰器会报错
装饰器本身是一个函数 通过@符号使用
类的装饰器
接收的参数是类的构造函数 创建类后立即执行
多个装饰器执行时 从下到上执行
function testDecorator(constructor: any) {
//在类上创建getName方法
constructor.prototype.getName = () => {
console.log("dell");
};
}
function testDecorator1(constructor: any) {
console.log("先执行");
}
//多个装饰器执行时 从下到上执行
@testDecorator
@testDecorator1
class Test {}
const test = new Test();
(test as any).getName();
//对装饰器进行 工厂函数包装
function testDecorator2(flag: boolean) {
if (flag) {
return function(constructor: any) {
constructor.prototype.getName = () => {
console.log("dell");
};
};
} else {
return function(constructor: any) {};
}
}
@testDecorator2(true)
class Test2 {}
const test2 = new Test2();
//(test2 as any).getName();
//new (...args: any[])=> {} 这是一个构造函数 接收很多都是any类型的参数 返回很多any类型的值
function testDecorator3<T extends new (...args: any[]) => {}>(constructor: T) {
//对类里的构造函数做扩展 会先执行原来的构造函数
return class extends constructor {
name = "lee";
getName() {
return this.name;
}
};
}
@testDecorator3
class Test3 {
name: string;
constructor(name: string) {
this.name = name;
}
}
const test3 = new Test3("dell");
//工厂模式 ->识别装饰器中新增的类方法
function testDecorator4() {
return function<T extends new (...args: any[]) => {}>(constructor: T) {
//对类里的构造函数做扩展 会先执行原来的构造函数
return class extends constructor {
name = "lee";
getName() {
return this.name;
}
};
};
}
const Test4 = testDecorator4()(
class {
name: string;
constructor(name: string) {
this.name = name;
}
}
);
const test4 = new Test4("dell");
test4.getName();
方法装饰器
普通方法接收的参数:target对应类的prototype原型,key对应装饰函数的名字,descriptor设置方法的属性
静态方法接收的参数:target对应类的构造函数
function getNameDecorator(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
//此函数是否可以在外部再次修改
descriptor.writable = false;
//对方法的内容做变更
descriptor.value = function() {
return "Decorator";
};
}
class Func {
name: string;
constructor(name: string) {
this.name = name;
}
//普通方法
@getNameDecorator
getName() {
return this.name;
}
//静态方法
// @getNameDecorator
// static getName1() {
// return 123;
// }
}
const func = new Func("dell");
console.log(func.getName());
访问器装饰器
function visitDecorator(
target: any,
key: string,
descriptor: PropertyDescriptor
) {}
class Visit {
private _name: string;
constructor(name: string) {
this._name = name;
}
get name() {
return this._name;
}
@visitDecorator
set name(name: string) {
this._name = name;
}
}
const visit = new Visit("dell");
visit.name = "1233333";
console.log(visit.name);
属性装饰器
function nameDecorator(target: any, key: string): any {
//target[key] = 'lee'; //这里修改的使原型上的属性,不是实例上的 获取方法->(names as any).__proto__.name
//创建一个替换name的descriptor,使name不能在外部被修改
const descriptor: PropertyDescriptor = {
writable: false
};
return descriptor;
}
class Name {
@nameDecorator
name = "Dell";
}
const names = new Name();
console.log(names.name);
参数装饰器
三个参数 target原型 method方法名 paramIndex参数的位置
function paramDecorator(target: any, method: string, paramIndex: number) {}
class Param {
getInfo(name: string, @paramDecorator age: number) {
console.log(name, age);
}
}
const param = new Param();
param.getInfo("dell", 18);
一个装饰器的小例子
使用装饰器统一判断uesrInfo是否是 undefined
const uesrInfo: any = undefined;
function catchErroe(msg: string) {
return function(target: any, key: string, descriptor: PropertyDescriptor) {
const fn = descriptor.value;
descriptor.value = function() {
try {
fn();
} catch (e) {
console.log(`${msg}有问题`);
}
};
};
}
class GetInfo {
@catchErroe("name")
getNAme() {
return uesrInfo.name;
}
@catchErroe("age")
getAge() {
return uesrInfo.age;
}
}
const getInfo = new GetInfo();