简介:最近工作很忙,复习周期也变长了,但是我会继续坚持每周复习。今天我们就来说说TypeScript在前端项目中的应用。至于为什么需要学习TypeScript,大家都很明显,目前的主流框架是Vue和React,相关生态的内部构建大部分都是使用TypeScript Think。原因是静态类型检查极大地提高了代码的可读性和可维护性,使问题识别变得非常方便。大家都能理解的Typescript官方定义是:
TypeScript 是Microsoft 开发的一种免费开源编程语言,是JavaScript 的超集,支持ECMAScript 6 标准。其设计目标是开发大规模应用程序。它可以编译为纯JavaScript,并且编译后的JavaScript可以在任何浏览器中运行。
本文将通过介绍ts的核心知识和现实生活中的例子,帮助你轻松掌握typescript。
总结语言学习需要学习和思维系统,前端也不例外。我们按照下图所示的结构来解释。
Text 目前我在项目开发中使用最多的是webpack。为了降低学习ts的难度,作者建议直接使用vue-cli3或者umi构建ts。创建一个项目以更快地开始您的TS 开发。
核心知识点1.基本类型
TypeScript 支持与JavaScript 几乎相同的数据类型,并且还提供有用的实用枚举。接下来我们简单介绍一下这些类型的使用方法。
//布尔类型let isCookie:boolean=true //数值类型let myMoney:number=12 //字符串类型let name:string=\’徐小溪\’ //数组类型。有两种表示方法,第一种可以后跟元素类型。 [],表示由该类型的元素组成的数组let arr:number[]=[1,2,2]//数组类型,使用数组泛型let arr:Array=[1,2,2]//元组类型允许已知的数组元素的数量和类型。每个元素的类型不必相同。 let xi: [string, number] //初始化xi=[11]; \’xu\’] ; //错误//枚举。您可以为一组值指定一个描述性名称。 enum ActionType {doing,ned, failed }let action:ActionType=ActionType.done //1//any,表示类型的任意值,允许绕过类型检查处理器会检查这些值let color:any=1color=\’red\’ //void 类型,如果函数没有返回值,返回类型通常设置为voidfunction getName(): void{ console.log(\’This is my name\’);}//非原始类型,即is,一个对象类型,表示除数字、字符串、布尔值、符号或null 或未定义之外的类型let a:object;a={props: 1} 复制代码。 上面的内容经常在打字稿中使用。这里值得添加的是打字稿类型断言。例如,这也是解决ts 警告的强大工具。要准确指定某些数据的数据类型,您可以执行以下操作:
let arrLen: number=(someValue as Array).length;//解决window 设置属性时出现ts 错误,但不要滥用(window as any).name=\’xuxi\’ 复制代码2. 接口
TypeScript 的核心原则之一是对值的结构进行类型检查。在TypeScript 中,接口的作用是命名这些类型并为您的代码或第三方代码定义契约。接下来,我们来看看如何定义和使用:接口。
Interface Product { name: string; size: number;weight: number;} let Product1:Product={ name: \’machine1\’, size: 20,weight: 10.5} 复制代码只要相应的属性存在,类型检查器就不会检查属性的顺序。没关系,因为类型是正确的。接下来,您还可以定义可选和只读属性。可选属性表示接口中的某些属性不是必需的,因此可读属性使接口中的某些属性成为只读且无法赋值。具体案例如下。
连接第三方SDK时经常会出现这种情况。后端响应。目前,索引签名可用于设置附加属性和类型。案件编号:
Interface App { name: string; color : number; [propName: string]: any;} 除了使用属性来描述常规对象之外,接口还允许您描述函数类型。必须定义接口的调用签名,并且参数列表中的每个参数都必须具有名称和类型。案件编号:
Interface MyFunc { (value:string, type: number): boolean;}//let myLoveFront: MyFunc; myLoveFront=function(value:string, type: number) { return type 1} 复制代码Vue 使用类,响应式开发很常见。可重用的组件和库既然ts可以描述函数的类型,那么它也可以描述类的类型吗?但是我们都知道定义一个类接口有点复杂。静态部件和实例的类型。如果类实现了接口,则仅对实例部分进行类型检查。构造函数位于类的静态部分,因此不在检查范围内。对于:在定义类接口时也应该注意这个特性。
接口TickConstructor { new (小时: 数字,分钟: 数字): TickInterface;}interface TickInterface { tick();}function createClock(ctor: ClockConstructor, 小时: 数字,分钟: 数字): TickInterface { return new ctor(小时, 分钟) ;}类DigitalClock 实现TickInterface { 构造函数(h: 编号,m: 编号){ }ticker() { console.log(\’xu xu\’); }}类MyTick 实现TickInterface { 构造函数(h: 编号,m: 编号){ } tick( ) { 安慰; log(\’tick tock\’); }}let digital=createClock(DigitalTick, 12, 17);let nano=createClock(MyTick, 7, 32);复制代码以了解这些主要接口类型以及如何使用它们。掌握。基本上可以从学习开始。
3. 班级
我们已经讨论了类接口的主题。这里,与js 类类似,TypeScript 类也有public、private 和protected 修饰符。具体含义如下。
public 在TypeScript 中,默认情况下成员是公共的,但您可以自由访问程序中定义的成员。标记为private 的成员与private 类似,但不能在声明为protected 的类之外访问它们。在某些情况下,仍然可以访问派生类中的成员,如下所示:
class Person { protected name : string; 构造函数(name : string) { this.name=name; }} class员工Person { 私人部门: string; super(name) 部门=部门} public getElevatorPitch() { return `你好,我的我的名字是${this.name},我在${this.Department} 工作。 ` }}复制代码类似地,您还可以为类中的属性定义只读修饰符。当谈到定义静态属性时,只有抽象类才值得讨论。
抽象类用作其他派生类的基类。 通常这些不会直接实例化。 与接口不同,抽象类可以包含其成员的实现细节。 Abstract 关键字用于定义抽象类以及在抽象类中定义抽象方法。
这里简单介绍一下抽象类相关的案例:
abstract class MyAbstract {constructor(public name: string) {}say(): void { console.log(\’say name: \’ + this.name) } AbstractsayBye(): void; //必须在派生类中实现。 AccountingMyAbstract extends MyAbstract { constructor() { super(\’小徐\’); //必须在派生类的构造函数中调用super() } SayBye(): void { console.log(\’关于小西的趣事。 \’) ; } getOther(): void { console.log(\’loading.\’); }}let education: MyAbstract //允许创建对抽象类型的引用。 //错误: 无法创建。类的抽象实例=new AccountingMyAbstract(); //允许抽象子类的实例化和赋值。 Department.say();Department.sayBye();Department.getOther(); //声明抽象方法时出错: 4. 类中不存在函数
上面解释了函数类型。这里主要的是JavaScript中的所有参数都是可选的,不能传递或传递。 如果未传递任何参数,则该值未定义。在TypeScript 中,您可以通过参数名称旁边的next 来实现可选参数的功能。 具体案例如下。
function createName(firstName: string, lastName : string) { if (lastName) return firstName + \’ \’ + lastName; else return firstName;} 复制代码。可选参数必须遵循必需参数。
5.仿制药
泛型可以用来创建可重用的组件,并且组件可以支持多种类型的数据。 这允许用户使用具有自己的数据类型的组件。泛型是TypeScript 中比较棘手的一个知识点,但它们非常重要,几乎所有第三方组件库都会用到。首先,我们看一个最简单的例子,
function iSay(arg: T): T { return arg;}//调用泛型函数let Come=iSay(123); 我复制了代码并将类型变量T 添加到了iSay 中。 T 对于捕获用户传递的类型(例如字符串)并使该类型可用非常有用。然后再次使用T 作为返回类型。现在您可以看到参数类型和返回类型是相同的。 这允许您跟踪有关函数中使用的类型的信息。
您还可以将泛型变量T 作为类型的一部分而不是整个类型来使用,这增加了其使用的灵活性。
function iSay(arg: T[]): T[] { console.log(arg.length) return arg;} 复制代码类似于定义函数类型,定义泛型接口并将泛型参数作为A 参数传递。也可以视为这使您可以清楚地知道正在使用哪种泛型类型。案例代码为:
Interface SayLove { (arg: T): T}//将通用参数视为接口范围的参数。 mySay1:SayLove=iSaylet mySay2:SayLoveArg=iSay 复制代码。 同样,您可以使用() 将泛型类型括起来,后跟类名。
class MyNumber {year: T;compute: (x: T, y: T)=T;} let myGenericNumber=new MyNumber(); 为了更精确地控制类的类型,您还可以这样定义:Masu.关注:
Interface NumberControl { length: number}class MyObject(arg: T):T { console.log(arg.length) return arg} 复制代码6. 高级类型
Typescript中的高级类型主要涵盖以下核心知识点:
交叉类型共享类型该类型的多态性索引类型查询运算符索引访问运算符交叉类型将多种类型组合为一种类型。可以堆叠多个现有类型以形成单个类型。以下是参考文献: 中的典型示例:
函数extend(first: T, Second: U): T U { let result={}; for (将id放在第一位) { (结果)[id]=(first)[id] } for (将id放在第二位) { if (!result .hasOwnProperty(id)) { (result)[id]=(second)[id]; } return result;}复制代码此时,在上面的代码中,返回值是用字符表示的。有T型和U型。
联合类型指示值是多种类型之一。 每种类型均由竖线(|) 分隔,因此number | string | boolean 表示该值是数字、字符串或布尔值。具体例子如下:
let name: string |number=\’xuxiaoxi\’functionsayName(name: string):(string|number) { return name }复制代码: 注意,如果值为union 类型,则只能访问该union 的所有类型。输入共享成员。
另一个常见的要求是,在实现自己的类之后,需要支持对类方法的链接调用。此时,TypeScript 需要表示该类型包含的特定A 子类型。类或接口。 这称为F 界多态性。为了支持typescript 中的链,你可以这样写:
class MyCalculator { public 构造函数(number=0) { } public add(n: number): this { return this.value +=n } public multiply(n: number): this { this.value *=n }; 更多操作. } let v=new MyCalculator(2).multiply(5).add(1); 接下来需要了解的知识点是索引查询运算符。一般表示为keyof。 对于任何类型T,keyof T 的结果是T 上已知公共属性名称的并集。 例如,定义一个名为Animal: 的接口。
Interface Animal { cat: string;} let AnimalProps: keyof Animal; //\’cat\’ | \’dog\’ 的代码与\’cat\’ | \’dog\’ 兼容。 不同的是,如果给Animal 添加其他属性,例如pig: 字符串,Animal 的键将自动变为\’cat\’ \’dog\’ | \’pig\’。
7. 命名空间
命名空间的主要功能是组织你的代码,以便你可以记录它的类型,而不必担心与其他对象的名称冲突。 使用命名空间非常简单,因此我将使用互联网上最受欢迎的D3 作为示例。这是代码:
导出命名空间D3。 var d3: D3.Base; 复制代码8. 使用第三方库了解了上面的基础知识后,我们以常用的Sho 为例来看看如何使用。正确的使用说明如下:
//安装lodash和相应的类型文件npm install –save lodash @types/lodash//在代码中import * as _ from \’lodash\’;_.padStart(\’Hello xuxiaoxi!\’, 12, \’ \’ );这。代码9.声明文件声明文件也是一个非常重要的知识点。当你使用未声明的全局函数或变量时,Typescript 经常会报错,因此在相应位置添加并放置xxx.d.ts 文件。声明必要的变量,ts 将自动检索文件并解析它。这里有一些学习:的案例供参考。
//global.d.ts//声明一个全局变量destroy var name: string; //声明一个全局函数function Say(name: string): void; //声明一个带有属性的对象myObj { functionsay (s: string): string; Money: number;}//可复用的接口Interface Animal { kind: string;weight : number;}declare function findAnmiate(animal:Animal):void复制代码当然,除了这里列出的之外,你还可以定义有用的声明。
React + Typescript 项目实践1. 使用umi 构建React + Typescript 项目
为了帮助大家开始TypeScript 开发,我们将使用umi 构建一个支持ts 的项目。刚接触这方面的朋友,可以参考作者之前学习umi的文章。
2.定义全局声明文件
为了处理全局声明以及与第三方库的兼容性,请在项目src 目录中创建global.d.ts 作为全局声明文件。
3.使用ts实现工具库。例如,创建一个utils目录,用于存放工具类或通用库。我们将在这里创建最简单的示例。
/*** 生成uuid */constuuid=():string={lets:Array=[];lethexDigits:string=\’0123456789abcdef\’;for(leti=0; i 36; i++) {s[i]=hexDigits.substr(Math.floor ) (Math.random() *0x10), 1);}s[14]=\’4\’;s[19]=hexDigits.substr((s[19]0x3) |0x8, 1);s[8 ]=s[13]=s[18]=s[23]=\’-\’;letuuid=s.join(\’\’);returnuuid;};//可以从外部type.ts文件中获取interface Params { [propName: string ] : string |number}/** * 反转对象的reverseJson键值对* @param {object} 需要反转的对象* @param {object} target 需要反转的目标对象*/constverseJson=( obj:Params={ }, target:Params={}):Params={ Object.keys(obj).forEach((key:string)={ target[obj[key]]=key }) return target}根据自己的需求复制代码即可实施相应的包装。
4. 在React 组件中使用typescript
作者将在接下来的文章中继续实现这一章,让大家具体了解现实世界的TypeScript 开发。
最后,如果您想了解更多H5游戏、webpack、node、gulp、css3、javascript、nodeJS、canvas数据可视化等前端知识和实践,欢迎加入我们《趣谈前端》欢迎学习和讨论。汇集了前端的边界。
本文和图片来自网络,不代表火豚游戏立场,如若侵权请联系我们删除:https://www.huotun.com/game/647867.html