摘要:接下来来看一段代码示例语法与语言比较当类型不对的时候,会提示错误编译后语法联想大致可以把它看成是加了类型系统的。
一篇文章学会 TypeScript (内部分享标题:TypeScript 基础)
这篇文章是我在公司前端小组内部的演讲分享稿,目的是教会大家使用 TypeScript,1、什么是 TypeScript?
这篇文章虽然标着基础,但我指的基础是学完后就能够胜任 TypeScript 的开发工作。
从我分享完的效果来看,大家都学会了,效果还是好的。我把这篇分享稿发布出来,
希望能对大家的 TypeScript 学习有所帮助。
TypeScript 是由微软发布的一款开源的编程语言。它是 JavaScript 的超集(兼容 JavaScript 代码),其代码必须经过编译后,方可在 JavaScript 环境中运行,核心功能是类型系统和可以提前使用 ES 的新特性。
接下来来看一段代码示例:
// TypeScript 语法 function add(x: number, y: number): number { const res: number = x + y; return res; } // 与 C 语言比较 int add(int x, int y) { int res = x + y; return res; }
当类型不对的时候,IDE 会提示错误:
编译后:
// JavaScript 语法 function add(x, y) { const res = x + y; return res; }
联想:大致可以把它看成是加了类型系统的 Babel。
问题:为什么要学习 TypeScript?类型系统可以在代码编译阶段就可以发现潜在的变量类型问题,甚至在开发阶段,IDE 就可以帮助我们找到这些潜在的问题,避免了项目在上线后才发现变量类型不对的错误。
TypeScript 是前端开发的趋势,有些特性还可能会成为 ES 的新标准,Vue 3.0 也会采用 TypeScript 作为开发语言,当你想看源码的时候不至于看不懂,跟着趋势走肯定是没错的。
减少类型校验等无用的代码书写。
可以提前享受 ES 新特性带来的便利。
向 qian 看,qian 途。
2、快速上手,三步走 第一步:全局安装 TypeScript$ yarn global add typescript // 测试是否安装成功 $ tsc -v Version 3.4.5第二步:创建 .ts 文件
// add.ts function add(x: number, y: number): number { const res: number = x + y; return res; } export default add;第三步:编译
$ tsc add.ts
// add.js function add(x, y) { const res = x + y; return res; } export default add;文件监听,实时编译
适用于边开发边看结果的情况:
$ tsc -w add.ts Starting compilation in watch mode... Watching for file changes.3、TypeScript 的基本类型
// 布尔值 let isDone: boolean = false; // 数值 let age: number = 12; // 字符串 let name: string = "Jay"; // 数组 let list: number[] = [1, 2, 3]; let list: Array4、类和接口= [1, 2, 3]; // 对象 let mokey: object = {name: "wu kong"}; // 空值,表示没有返回值 function print(): void {} // 任意值 let goods: any = {}; let goods: any = 2019; // 未指定类型,视为任意值 let goods; // 类型推断 let name = "Jay"; name = 123; // 报错 // 联合类型 let name: string | number; name = "Jay"; name = 123;
类是对属性和方法的封装
类的示例:
// 跟 JavaScript 的类相似,多了访问控制等关键词 class Monkey { public height: number; private age: number = 12; public static mkName: string = "kinkong"; private static action: string = "jump"; constructor(height: number) { this.height = height; } public getAge(): number { return this.age; } } const monkey = new Monkey(120); monkey.getAge(); const height = monkey.height; const age = monkey.age; // 报错 const mkName = Monkey.mkName; const action = Monkey.action; // 报错
class Animal { move(distanceInMeters: number = 0) { console.log(`Animal moved ${distanceInMeters}m.`); } } class Dog extends Animal { bark() { console.log("Woof! Woof!"); } } const dog = new Dog(); dog.bark(); dog.move(10);
protected 和 private 都不能从外部访问
protected 可以被继承,private 不可以
class Person { protected name: string; private age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } } class Employee extends Person { private readonly initial: string = "abc"; private readonly department: string; constructor(name: string, department: string) { super(name, 1); this.department = department; } public getElevatorPitch() { return `Hello, my name is ${this.name} and I work in ${this.department}.`; } public getAge() { return this.age; } } let howard = new Employee("Howard", "Sales"); console.log(howard.getElevatorPitch()); console.log(howard.name); // error
let passcode = "secret passcode"; class Employee { private _fullName: string; get fullName(): string { return this._fullName; } set fullName(newName: string) { if (passcode && passcode == "secret passcode") { this._fullName = newName; } else { console.log("Error: Unauthorized update of employee!"); } } } let employee = new Employee(); employee.fullName = "Bob Smith"; if (employee.fullName) { console.log(employee.fullName); }
class Point { x: number; y: number; } interface Point3d extends Point { z: number; } let point3d: Point3d = {x: 1, y: 2, z: 3};
接口是用来定义规范的,常常用作类型说明。
接口的示例:
// 定义规范,限定类型 interface Point { x: number; y: number; // 可选属性 z?: number; } let pt: Ponit = {x: 1, y: 1, z: 1}; function setPoint(point: Point): void {} setPoint({x: 1, y: 1}); // 实现接口 class point implements Point { x: number; y: number; constructor(x: number, y: number) { this.x = x; this.y = y; } public getPoint(): object { return { x: this.x, y: this.y, } } } const p = new point(3, 4); p.getPoint();
interface Shape { color: string; } interface Square extends Shape { sideLength: number; }
interface ClockConstructor { new (hour: number, minute: number); } class Clock implements ClockConstructor { currentTime: Date; constructor(h: number, m: number) { } }5、type、 namespace 和泛型 type 定义新类型
当 TypeScript 提供的类型不够用时,可以用来自定义类型,供自己使用。
// type 定义新类型,相当于类型别名 type myType = string | number | boolean // 使用: const foo: myType = "foo" // type 定义函数类型 type hello = (msg: string) => void // type 对象类型 type WebSite = { url: string; title: number; }namespace 命名空间
命名空间主要有两个方面的用途:
组织代码。组织一些具有内在联系的特性和对象,能够使代码更加清晰。
避免名称冲突。
namespace Validator { export interface StringValidator { isAcceptable(s: string): boolean; } const lettersRegexp = /^[A-Za-z]+$/; const numberRegexp = /^[0-9]+$/; // 当声明一个命名空间的时候,所有实体部分默认是私有的,可以使用 export 关键字导出公共部分。 export class LettersOnlyValidator implements StringValidator { isAcceptable(s: string) { return lettersRegexp.test(s); } } export class ZipCodeValidator implements StringValidator { isAcceptable(s: string) { return s.length === 5 && numberRegexp.test(s); } } } new Validator.LettersOnlyValidator(); interface MyClassMethodOptions { name?: string; age?: number; } namespace MyClass { export interface MyClassMethodOptions { width?: number; height?: number; } }
///泛型const v = new Validator.LettersOnlyValidator();
泛型允许在强类型程序设计语言中编写代码时,使用一些以后才指定的类型,在实际调用时才去指定泛型的类型。
举例:
// 模拟服务,提供不同的数据。这里模拟了一个字符串和一个数值 const service = { getStringValue: function() { return "a string value"; }, getNumberValue: function() { return 20; } }; // 处理数据的中间件 function middleware(value: string): string { return value; } // 没问题 middleware(service.getStringValue()); // 报错:参数类型不对 middleware(service.getNumberValue()); // 设成 any 行不行? function middleware(value: any): any // 多写几个 middleware 行不行? function middleware1(value: string): string { ... } function middleware2(value: number): number { ... } // 改为泛型 function middleware(value: T): T { return value; } // 使用 middleware (service.getStringValue()); middleware (service.getNumberValue());
更多内容查看文章:泛型
6、xxx.d.ts声明文件如果把 add.js 发布成一个 npm 包,别人在使用的时候 IDE 的提示往往都不太友好:
那么如何能让 IDE 给 add 方法加上类型提示和参数提示呢?
TypeScript 提供了 xxx.d.ts 文件来给 IDE 使用。
xxx.d.ts 叫做声明文件,一般用于类型提示和模块补充,可以自动生成,也可以手动编写,一般情况下是不用我们手动编写的。
// 加上 -d 参数,就会生成 add.d.ts 文件 $ tsc -d add.ts
// add.d.ts declare function add(x: number, y: number): number; export default add;
declare 关键字
用于声明你需要的变量、函数、类等,声明以后 IDE 就可以根据它来进行类型提示。
如果有 add.d.ts 文件,那么它就承担了类型提示的任务:
同时也相当于 add 方法的接口文档:
手动创建声明文件有以下两个场景会去手动创建这个文件:
给未使用 TypeScript 的 js 模块编写声明文件,可以当做交接文档用;使用别人没有写声明文件的 js 库。
模块补充。
// 定义模块补充的语法 declare module "filePath" { }
module-augmentation
使用场景:vue-shim.d.ts 文件,为了让 TypeScript 识别 .vue 文件。
// 文件内容 declare module "*.vue" { import Vue from "vue"; export default Vue; }
增强类型以配合插件使用
7、配置文件 冗长的参数指定输出目录:
$ tsc -d --strict -m ESNext --outDir lib index.ts
tsc 的所有参数可以通过执行:tsc -h来查看。
使用 tsconfig.json 配置文件避免书写冗长的命令,丰富的配置项。
生成 tsconfig.json 文件:
$ tsc --init
常用配置项解读:
{ "compilerOptions": { "target": "ES5", /* target用于指定编译之后的版本目标 version: "ES3" (default), "ES5", "ES2015", "ES2016", "ES2017","ES2018" or "ESNEXT". */ "module": "ESNext", /* 用来指定要使用的模块标准: "none", "commonjs", "amd", "system", "umd", "es2015", or "ESNext". */ "declaration": true, /* 生成对应的 ".d.ts" 声明文件 */ "outDir": "./lib", /* 指定编译输出目录 */ "esModuleInterop": true, /* 通过为导入内容创建命名空间,实现CommonJS和ES模块之间的互操作性 */ "experimentalDecorators": true, /* 启用 ES7 装饰器语法 */ } }
查看更多配置项
配置后,执行以下命令,就会读取配置文件:
$ tsc add.ts8、使用 TypeScript 开发 web 应用
上述的方法适用于开发命令行工具,比如 @xiyun/cli,开发 web 应用还是不太方便。
如果想要方便地开发 web 应用,比如:开启前端服务、模块热加载等,就需要配合构建工具使用。
配合 webpack 开发 web 应用点击查看配合 webpack 开发 web 应用源码
配合 parcel,零配置开发 web 应用parcel:极速零配置 Web 应用打包工具。
联想:可以看成是已经配置好了的 webpack。
全局安装 parcel 工具:
$ yarn global add parcel-bundler
运行:
$ parcel index.html
它就会帮你生成 package.json,自动安装 typeScript,启动好开发服务,并支持热加载。
9、在 Vue 和 React 项目中使用 让 Vue 支持 TypeScript最方便快捷:vue create my-app,选择 TypeScript。
如果要改造现有项目:
增加 dev 依赖包:
"devDependencies": { "@vue/cli-plugin-typescript": "^3.8.0", "typescript": "^3.4.3", }
增加 tsconfig.json 配置
更改文件后缀:main.js --> main.ts
组件中指定 lang:
在 src 目录下加上:vue-shim.d.ts 文件,为了让 TypeScript 识别 .vue 文件。
// 文件内容 declare module "*.vue" { import Vue from "vue"; export default Vue; }
Vue 支持 TypeScript 的配置参考
如果想要用这种语法来写 Vue 组件:
import { Component, Prop, Vue } from "vue-property-decorator"; @Component export default class HelloWorld extends Vue { @Prop() private msg!: string; }
那么需要加上这两个依赖:
"dependencies": { // 官网出的ts支持包 "vue-class-component": "^7.0.2", // 对ts支持包更好封装的装饰器 "vue-property-decorator": "^8.1.0" },
Vue 官方对 TypeScript 的说明
创建支持 TypeScript 的 React 项目创建应用时加上--typescript参数即可:
$ create-react-app my-app --typescript参考资料
TypeScript 官方文档
TypeScript Declare Keyword
Vue 对 模块补充的说明
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/104318.html
摘要:周末是时隔两月的家人团聚,而每次内容的准备平均需要我集中精力工作小时,所以第期的内容今早才准备好,对不住大家了。下面是本周精选内容,请享用。本文作者王仕军,商业转载请联系作者获得授权,非商业转载请注明出处。 showImg(https://segmentfault.com/img/remote/1460000009742537?w=1240&h=509); 周末是时隔两月的家人团聚,而...
摘要:前言讲起前端,我们就不能不讲与,在这两种技术广泛应用的今天,他们的扩展也是层出不穷,的扩展有等,的超集有等。如下注意你的样式文件一定要在引入前先引入。截止目前,已经发布了最新的版本。 前言:讲起前端,我们就不能不讲CSS与Javascript,在这两种技术广泛应用的今天,他们的扩展也是层出不穷,css的扩展有Less、Sass、Stylus等,js的超集有Typescript等。今天我们就简...
这只是个开头 说在最前面,本文是一个系列文章的开头, 这个系列里我会讲如何用typescript开发一款支持pc和手机端的手势库any-touch, 以及通过jest让你的代码测试覆盖率100%. showImg(https://segmentfault.com/img/bVbp3B0?w=936&h=246); 目录 用TypeScript开发手势库 - (2)tsconfig.json & r...
本文收集学习过程中使用到的资源。 持续更新中…… 项目地址 https://github.com/abc-club/f... 目录 vue react react-native Weex typescript Taro nodejs 常用库 css js es6 移动端 微信公众号 小程序 webpack GraphQL 性能与监控 高质文章 趋势 动效 数据结构与算法 js core 代码规范...
阅读 929·2021-11-17 09:33
阅读 396·2019-08-30 11:16
阅读 2451·2019-08-29 16:05
阅读 3319·2019-08-29 15:28
阅读 1372·2019-08-29 11:29
阅读 1922·2019-08-26 13:51
阅读 3363·2019-08-26 11:55
阅读 1182·2019-08-26 11:31