当前位置: 首页 > news >正文

【TS】加深TS理解的开发实战示例代码

文章目录

    • TS接口
      • 开发实战:基于类类型接口设计实现日期时间应用
      • 开发实战:基于单接口继承设计实现计算周长的应用
      • 开发实战:基于多接口继承设计实现计算周长和面积的应用
      • 开发实战:基于混合类型接口设计实现计数器应用
    • TypeScript类
      • 开发实战:设计实现存取器应用
    • TypeScript 函数
      • 开发实战:箭头函数与this关键字应用
    • TypeScript 泛型
      • 开发实战:泛型变量应用
      • 开发实战:泛型类型应用
      • 开发实战:泛型接口应用
      • 开发实战:泛型类应用
    • TypeScript 高级类型
      • 类型别名
      • 映射类型

TS接口

开发实战:基于类类型接口设计实现日期时间应用

interface ITimeDate {curTime: Date;setTime(cur: Date): void;getTime(): Date;
}class CTime implements ITimeDate {curTime: Date;constructor(cur: Date) {this.curTime = cur;}setTime(cur: Date): void {this.curTime = cur;}getTime(): Date {let curTime: Date;if(this.curTime) {curTime = this.curTime;} else {curTime = new Date();}return curTime;}
}let ct: CTime = new CTime(new Date());
console.log(ct.getTime());let newTime: Date = new Date("2021/10/21 00:00:00");
ct.setTime(newTime);
console.log("New time is: " + ct.getTime());

开发实战:基于单接口继承设计实现计算周长的应用

interface IShape {girth: number;
}
interface ISqure extends IShape {shapeType: string;getGirth(): number;
}class CSquare implements ISqure {shapeType: string;girth: number;constructor(sideLength: number) {this.shapeType = 'Square';this.girth = sideLength * 4;}getGirth(): number {return this.girth;}
}let cs: CSquare = new CSquare(6);
console.log(cs.shapeType + 'sideLength is 6, then girth is ' + cs.getGirth() + '.'
);

声明了一个表示几何图形的抽象接口IShape,其中包括一个表示图形周长的属性girth.

同时声明了一个继承自抽象接口IShape的接口ISquare,用来描述正方形。

最后定义了一个实现接口ISquare的类CSquare。

开发实战:基于多接口继承设计实现计算周长和面积的应用

前一个应用是通过单接口继承实现的,其实TypeScript多接口继承功能更常用。

我们对上述示例进行改进,通过TypeScript多接口继承设计实现同时计算正方形周长和面积的应用。

interface IGirth {girth: number;
}
interface IArea {area: number;
}interface ISquareB extends IGirth, IArea {shapeType: string;getGirth(): number;getArea(): number;
}
class CSquareB implements ISquareB {shapeType: string;girth: number;area: number;constructor(sideLength: number) {this.shapeType = "Square";this.girth = 4 * sideLength;this.area = sideLength * sideLength;}getGirth(): number {return this.girth;}getArea(): number {return this.area;}
}let csB: CSquareB = new CSquareB(6);
console.log(csB.shapeType + " sideLength is 6, then girth is " + csB.getGirth() + ".");
console.log(csB.shapeType + " sideLength is 6, then area is " + csB.getArea() + "." );

开发实战:基于混合类型接口设计实现计数器应用

下面通过TypeScript混合类型接口设计实现一个具有计数器(初始化、累加、调整步长和重置)功能的应用。

interface ICounter {(s: string): void;current: number;interval: number;count(): void;setInterval(i: number): void;reset(): void;
}function getCounter(): ICounter {let counter = <ICounter>function(s: string): void {console.log(s);}// init countercounter.current = 0;counter.interval = 1;counter.count = function() {counter.current += counter.interval;console.log('Now current count is: ' + counter.current + '.');}counter.setInterval = function(i: number) {counter.interval = i;console.log('Now interval changes to:' + counter.interval + '.');}counter.reset = function() {counter.current = 0;console.log('Now current count is reset to 0.');}return counter;
}let c = getCounter();
console.log('counter typescript app:');
c.count();
c.setInterval(5);
c.count();
c.reset();
c.setInterval(1);
c.count();

最终结果:

counter typescript app:
Now current count is: 1.
Now interval changes to:5.
Now current count is: 6.
Now current count is reset to 0.
Now interval changes to:1.

ICounter 接口定义了一个函数类型和一些属性和方法:

interface ICounter {(s: string): void; // 这是一个函数类型current: number;   // 这是一个属性interval: number;  // 这是一个属性count(): void;     // 这是一个方法setInterval(i: number): void; // 这是一个方法reset(): void;     // 这是一个方法
}

通过类型断言 ,我们确保 counter 变量不仅包含一个函数,还包含 current、interval 属性以及 count、setInterval 和 reset 方法。这样,TypeScript 编译器就会检查这些属性和方法是否都被正确地初始化和实现。

说明如下代码意思:

let counter = <ICounter>function(s: string): void {console.log(s);
}
  • 定义一个匿名函数 function(s: string): void { console.log(s); }。
  • 使用类型断言 将这个匿名函数断言为 ICounter 类型。

在 TypeScript 中,类型断言有两种语法形式:

  • 使用尖括号 ,例如 。
  • 使用 as 关键字,例如 as ICounter。

TypeScript类

开发实战:设计实现存取器应用

在TypeScript类语法中,支持通过getters/setters存取器方式来执行对类成员的访问操作,这种方式能帮助开发人员有效地控制对类成员的访问。在TypeScript类中,设计存取器需要使用get(获取)和set(存储)修饰符来定义。

class CGetSet {private _name: string;constructor(theName: string) {this._name = theName;}get Name(): string {return this._name;}set Name(theName: string) {theName = theName.trim();if(theName && theName.length) {this._name = theName;} else {console.log('error:theName is empty.');}} 
}let gs = new CGetSet('set&get');
console.log(gs.Name); // set&get
gs.Name = 'reset set&get';
console.log(gs.Name); // reset set&get

TypeScript 函数

开发实战:箭头函数与this关键字应用

let userInfo = {uname: 'zhangsan',printInfo() {return function () {return {name: this.uname}}}
}const ui = userInfo.printInfo();
console.log(ui().name)

上面代码中this会报错,编译信息提示this关键字的类型为Any的错误。

方式一,用箭头函数调整:

let userInfo = {uname: 'zhangsan',printInfo() {return () => {return {name: this.uname}}}
}const ui = userInfo.printInfo();
console.log(ui().name)

方式二,使用 that 或 self 变量:

let userInfo = {uname: 'zhangsan',printInfo() {const self = this;return function () {return {name: self.uname}}}
}

方式三:使用 apply 或 call 方法

可以在调用嵌套函数时使用 apply 或 call 方法来显式设置 this。

let userInfo = {uname: 'zhangsan',printInfo() {return function (this: typeof userInfo) {return {name: this.uname}}}
}const ui = userInfo.printInfo();
console.log(ui.apply(userInfo).name)

TypeScript 泛型

开发实战:泛型变量应用

function echoVar<T>(arg: Array<T>): Array<T> {console.log('arg length:' + arg.length)return arg;
}console.log(echoVar([1, 2]))
console.log(echoVar(['a', 'b']))

上述代码定义了一个泛型函数echoVar,参数arg定义为类型<T>的数组形式Array<T>。

开发实战:泛型类型应用

使用泛型类型定义泛型函数的应用

function echo_type<T>(arg: T): T {return arg;
}let arrow_echo_type: <T>(arg:T) => T = echo_type;console.log(arrow_echo_type("Hello")); // Hello

上述代码,通过泛型类型<T>(arg:T)定义了一个泛型函数变量arrow_echo_type,并指定为泛型函数echo_type。

另外,我们可以使用具有调用签名的对象字面量来定义泛型函数:

function echo_type<T>(arg: T): T {return arg;
}let liter_echo_type: {<T>(arg:T):T} = echo_type;
console.log(liter_echo_type("Hello")); // Hello

开发实战:泛型接口应用

我们可以将对象字面量“{<T>(arg:T):T}”单独封装为一个接口形式。

interface IGenericsEcho {<T>(arg: T): T;
}function fn_echo_generics<T>(arg: T): T {return arg;
}let echo_gen: IGenericsEcho = fn_echo_generics;
console.log(echo_gen('define generics func by interface'));

上述代码,声明了一个接口IGenericsEcho,通过对象字面量“<T>(arg:T):T”定义了泛型函数的类型。

通过泛型接口IGenericsEcho和泛型函数fn_echo_generics定义了一个函数变量echo_gen。

进一步在接口声明中直接加上类型<T>,写成真正的泛型接口形式。上述代码调整为如下:

interface IGenericsEcho<T> {(arg: T): T;
}function fn_echo_generics<T>(arg: T): T {return arg;
}let echo_gen_str: IGenericsEcho<string> = fn_echo_generics;
let echo_gen_num: IGenericsEcho<number> = fn_echo_generics;
console.log(echo_gen_str('define generics func by interface'));
console.log(echo_gen_num(123));

上面代码声明了一个泛型接口IGenericsEcho<T>,接口类型为“(arg:T):T”。

我们在使用该泛型接口定义函数变量echo_gen_num和echo_gen_str时,需要指定具体类型。

开发实战:泛型类应用

class EchoGenerics<T> {private _m_arg: T;constructor(arg: T) {this._m_arg = arg;}public echo(): void {console.log(this._m_arg)}
}let g_echo_str = new EchoGenerics<string>("Hello World");
g_echo_str.echo();
let g_echo_num = new EchoGenerics<number>(123);
g_echo_num.echo();

TypeScript 高级类型

类型别名

在类型别名中使用泛型来模拟接口功能的应用。

type StrNum = string | number;
type aliasGeneric<T> = {x: T;y: T;
}function getXY(ag: aliasGeneric<StrNum>) {if(typeof ag.x === 'number' && typeof ag.y === 'number') {console.log(ag.x + ag.y)}else if(typeof ag.x === 'string' && typeof ag.y === 'string') {console.log(`${ag.x} ${ag.y}`)}else {console.log('other alias-type generic')}
}let agStr: aliasGeneric<string> = {x: 'a',y: 'b'
}
getXY(agStr);let agNum: aliasGeneric<number> = {x: 1,y: 2
}
getXY(agNum);

映射类型

如下示例,通过映射类型方式将原接口IPerson的属性转换为只读属性:

interface IPerson {name: string;age: number;
}type TReadyOnly<T> = {readonly [p in keyof T]: T[p];
}type ReadyOnlyPerson = TReadyOnly<IPerson>;

通过映射类型方式将原接口IPerson的属性转换为可选属性:

interface IPerson {name: string;age: number;
}type TOptional<T> = {[p in keyof T]?: T[p];
}type OptionalPerson = TOptional<IPerson>;

http://www.mrgr.cn/news/33700.html

相关文章:

  • C++特性—左值与右值
  • Java接口详解
  • 【MySQL 03】表的操作
  • 上海数科(北京)律师事务所开业庆典圆满举行
  • 网络层协议 —— IP协议
  • C++标准库容器类——string类
  • 项目集成sharding-jdbc
  • 【鼠标滚轮专用芯片】KTH57913D 霍尔位置传感器
  • 作用域与作用域链
  • fas sklxj siaoj oisaj
  • 【系统架构设计师】论文模板:快速写好一篇架构设计师论文
  • Rabbitmq消息队列,安装,使用,三种工作模式
  • Vue工程师面试题
  • re题(39)BUUCTF-[FlareOn3]Challenge1
  • DNF Decouple and Feedback Network for Seeing in the Dark
  • 【LLM论文日更】| 俄罗斯套娃嵌入模型
  • 中国人工智能企业崛起:4000家背后的机遇与挑战
  • 感知算法引入时序模型的优势
  • 企业级-pdf预览-前后端
  • 4--SpringBoot项目中分类管理