文章目录
准备
为何要用 typescript
- 我们在定义一个函数,仅仅只是操作字符串, 但是人总会疏忽,在 js 中传递进去的对象,函数也一样能运行
- 由此,我们需要一个在运行前帮我们检测,并约束数据类型的语法
- 在
Angular
里面- 1.x更名为
AngularJS
- 2.x 以上都称之为
AngularlO
- 1.x更名为
起步
- 安装编译
TypeScript
语法到 js 语法的编译工具
npm install -g typesctipt
- 编写代码
function greeter(person: string){
return 'Hello,'+ person
}
let user = 'zm'
document.body.innerHTML = greeter(user)
tsc index.ts
常见错误处理
tsconfig.json
tsconfig.json
是 TypeScript 的编译选项文件,通过配置它来定制 TypeScript 的编译细节。
- 直接调用
tsc
,编译器会从当前目录开始去查找tsconfig.json
文件,逐级向上搜索父目录。 - 调用
tsc -p
,可以指定一个包含tsconfig.json
文件的目录进行编译。如果没有找到tsconfig.json
文件,TypeScript
会编译每个文件并在对应文件的同级目录产出。
一个 tsconfig.json
文件描述:
{
// 编译选项
"compilerOptions": {
// 输出目录
"outDir": "./output",
// 是否包含可以用于 debug 的 sourceMap
"sourceMap": true,
// 以严格模式解析
"strict": true,
// 采用的模块系统
"module": "esnext",
// 如何处理模块
"moduleResolution": "node",
// 编译输出目标 ES 版本
"target": "es5",
// 允许从没有设置默认导出的模块中默认导入
"allowSyntheticDefaultImports": true,
// 将每个文件作为单独的模块
"isolatedModules": false,
// 启用装饰器
"experimentalDecorators": true,
// 启用设计类型元数据(用于反射)
"emitDecoratorMetadata": true,
// 在表达式和声明上有隐含的any类型时报错
"noImplicitAny": false,
// 不是函数的所有返回路径都有返回值时报错。
"noImplicitReturns": true,
// 从 tslib 导入外部帮助库: 比如__extends,__rest等
"importHelpers": true,
// 编译过程中打印文件名
"listFiles": true,
// 移除注释
"removeComments": true,
"suppressImplicitAnyIndexErrors": true,
// 允许编译javascript文件
"allowJs": true,
// 解析非相对模块名的基准目录
"baseUrl": "./",
// 指定特殊模块的路径
"paths": {
"jquery": [
"node_modules/jquery/dist/jquery"
]
},
// typescript 编译过程中需要引入的库
"lib": [
"es2015",
"es2015.promise"
]
}
}
类型
布尔值
let isDone: boolean = false
数字
let num: number = 1111
字符串
let name: string = 'zj'
数组
let list: number[] = [1, 2, 3]
任意类型数组
let arr: any[] = [1, '2', 3, true, {name: 'zj'}]
枚举(更友好的名称,相当于键值对)
enum Color {red, green, blue}
let c: Color = Color.red; // 0 方式一 看做一个对象,key 可以是双向的,既可以通过索引取名称,也可以通过属性名获取
let msg: string = Color[1] // green 方式二 看做一个数组
Viod
- 一般作为函数没有返回值的表示,而不作为变量类型的声明
- 因为它没有任何类型
function test(): viod {
console.log('Hello Word')
}
Null 和 Undefined
类型断言
- 可以理解为 强制类型声明
类型断言有两种形式。一种是 “尖括号” 语法:
let value: any = "this is a string"
let str: string = <string>value
另一个为 as
语法:
let value: any = "this is a string"
let str: string = value as string
类
基本使用(里面不要放 let / const )
class Greeter{
greeting: string;
constructor(message: string){
this.greeting = message;
}
greet(){
return "Hello, "+ this._greeting;
}
}
let greeter = new Greeter('word');
继承语句
class student extends Person{}
new Student();
公共,私有与受保护的修饰符
公共(默认和不写一样)
- public 代表可以在 class{} 以外的地方访问
class Person {
public name: string = 'abc';
private age: number = 50;
protected money: number = 10000;
}
class Son extends Person {
getParentAge(){
this.age // 报错, 受保护的无法访问
}
getParentMoney(){
this.money // 10000
}
}
let p = new Person();
p.name // 可以访问
p.money // 无法访问
p.age // 无法访问
readonly 只读修饰符
- 类似于之前使用的
const
,只能被赋值一次,不能在被赋值
class Person {
public readonly name: string = 'zj'
}
let p = new Person();
p.name = '1111' // Error
静态属性(static)
- 使用类名 . 属性名 访问
- 类似构造函数的的属性
function P(){}; P.age = 123
- 静态属性不是实例的属性
function P(){};P.prototype.age = 10
- 组合写法
class Xxx{
public static readonly name: string = 'zh'
}
Xxx.name
get/set 存储器
error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
因为默认使用的是 ES3 的代码规范编译的,可以提高 ES5 的代码规范版本
tsc -t ES5 .\08.getter_setter.ts
- 可以运行
class Person {
private _age: number = 13;
public get age(): number {
return this._age
}
public set age(v: number){
this._age = v
}
}
let p = new Person()
p.age = 100;
console.log(p.age)
- 小结:
public/readonly
这类修饰符是在编译期间对代码的约束,而不能管到编译结束后的约束- 静态不能访问实例,但是实例可以访问静态(历史不能学人,但是人可以学历史)
抽象类
- 每个
class
的属性定义都很随意。可以通过抽象类来管理其必备那些属性及方法 - 抽象类中可以有抽象方法(给子类实现),也可以有已实现的方法
abstract class Animal {
abstract makeSound(): void;
move(): void{
console.log('动物们正在移动...')
}
}
- 第二行:子类必须实现,或者子类也是抽象类并声明该方法为抽象方法
接口(约定、规范)
- 偏向于规则定义
- 只定义,不实现的抽象类
- 接口可以用来实现,而不是继承,所以对应类必须实现接口的方法和属性
额外属性检测
- 有时候我们在应用接口的时候,可能会额外的添加一些属性或方法,这时候就需要额外类型检测
interface Person {
readonly name: string;
readonly age: number;
[propName: string]: any; // 添加这一行代码
}
函数类型
interface SearchFunc {
(source: string, subString: string): boolean
}
let mySearch: SearchFunc = (src, sub) =>{ // 可以省略类型声明
let result = src.search(sub)
return result > -1
}
- 有一个参数列表
(source: string, subString: string)
- 参数列表中必须有
name: type
- 参数列表中必须有
- 还有 返回值
boolean
(类型的函数定义) - 调用方法还是一样的
- 在调用中 形参类型必须与接口中的参数列表保持一致
- 形参可以不用声明类型,方法也可以不声明类型,
typescript
会自动检测是否与接口一致
数组类型
interface ArrayType {
[index: number]: string; // 声明数组成员
}
let arr: ArrayType;
arr = ['Dog', 'Cat'];
类实现接口
- 一个类只能继承一个类(单继承),一个类可以实现多个接口,都是定义规则
// 定义一个 动物的基本信息接口
interface Animal {
kind: string; // 种类
// 介绍动物
detail(kind: string, sex: string): string
}
class Dog implements Animal{
kind = '11'
detail(kind: string, sex: string): string{
return kind + sex
}
}