「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」。
TypeScript语言规范与基本应用
- JavaScript的超集,最后将被编译为javascript
安装
yarn add typescript --dev
编译
yarn tsc 01.ts
将会生成一个同名的js文件 ts文件
const hello = (name:string) =>{
console.log(`hello,${name}`)
}
hello("TypeScript")
生成的js文件
var hello = function (name) {
console.log("hello," + name);
};
hello("TypeScript");
配置文件
1.运行命令生成tsconfig.json的文件
yarn tsc --init
数据类型
- 原始数据类型
const a:string="foo"
const b:number = 100 //NaN Infinity
const c:boolean = true //false
// const c:boolean = null 如果配置文件中的严格模式 为 false 则以上三种数据的值可以为null
const c:void = undefined //标记函数的返回值类型 严格 undefined 非严格 null 与 undefined
const c:undefined = undefined
const c:null = null
const h:symbol = Symbol()
- 标准库的声命 1.通过配置文件中的target来修改 2.通过修改配置文件中的"lib"选项
"lib":["ES2015","DOM"]
- 中文的错误消息 编译时使用
yarn tsc --locale zh-CN
- 作用域问题 1.放在一个立即执行函数中
(function(){
const h:string="hello"
})()
2.在文件中添加一个 export {}
const h:string="hello"
export {}
- Object类型
泛指 非原始数据类型
const foo:object=function(){} //{} //[]
// Object类型可以是以上三种 object是小写的
const obj:{foo:number,bar:string} = {foo:123,bar:"string"}
// 类似字面量的方式,更好的方式是用接口的方式
- 数组类型 1.泛指类型
const arr1:Array<number> = [1,2,3]
const arr1:number[] = [1,2,3]
- 元组类型
const tuple:[number,string] = [18,"zce"]
// const age = tuple[0]
// const age = tuple[1]
const [age,name] = tuple
- 枚举类型
const post = {status:3} //0 //1 // 2
// 通过enum关键字来声明枚举值
enum PostStatus{
Draft=0,
Unpublished = 1,
published = 2
}
const post = {status:PostStatus.published}
enum PostStatus{
Draft,
Unpublished ,
published
}
// 不给枚举变量指定值的话,默认会从0开始累加
enum PostStatus{
Draft=6,
Unpublished ,
published
}
// 假如给第一个变量指定一个值,后续的变量会在第一个值的基础上自增
// 枚举值也可以是字符串
const enum PostStatus{
Draft=0,
Unpublished = 1,
published = 2
}
// 加 const 表示 常量枚举
- 函数类型
function func1(a:number,b:number):string{
return "func1"
}
func1(100,200)
// 实参 必须与形参相同
function func1(a:number,b?:number):string{
return "func1"
}
function func1(a:number,b:number = 100,...rest:number[]):string{
return "func1"
}
func1(100)
// 加?或者是默认值 表示参数可选 可选参数 必须出现在参数的最后
- 函数表达式类型
const func2:(a:number,b?:number)=>string = function (a:number,b?:number):string{
return "func1"
}
- 任意类型
let foo:any = "string"
// any 类型是不安全的 轻易不使用
- 隐式类型推断
let age = 18 //隐式推断为number
age = "string" //语法报错
let foo
foo = 100
foo = "string"
// 隐式推断为 any类型
- 类型断言
// 假定这个nums来自 一个明确的接口
const nums = [110,120,119,112]
const res = nums.find(i=>i>0)
// 此时 ts 并不知道 res 一定会返回一个 number 我们需要下面这儿样做 告诉ts 此处的 res 肯定会是个 number 即类型断言
const num1 = res as number
// 或者
const num2 = <number>res //jsx中 不能使用 会冲突
- 接口
// 接口定义对象
interface Post{
title:string
content:string
}
function printPost(post:Post){
console.log(post.title)
sonsole.log(post.content)
}
printPost({title:'hello typescript',content:"a javascript superset"})
- 可选成员
interface Post{
title:string
content:string
subtitle?:string
}
- 只读成员
interface Post{
title:string
content:string
subtitle?:string
readonly summary:string
}
- 动态用法
interface Cache{
[key:string]:string
}
- 类 描述一类具体事务的抽象
class Person{
name:string
age:number
constructor(name:string,age:number){
this.name = "name"
this.age = 23
}
sayHi(msg:string):void{
console.log(`I am ${this.name},${msg}`)
}
}
- 类的访问修饰符 控制类当中的成员的可访问级别
class Person{
public name:string //公有成员 默认是公有
private age:number //私有变量
protected gender:boolean
constructor|(name:string,age:number){
this.name = name
this.age = age
this.gender = true
}
sayHi(msg:string):void{
console.log(`I am ${this.name},${msg}`)
console.log(this.age)
}
}
const tom = new Person('tom',18)
console.log(tom.name)
console.log(tom.age) //报错 因为age是私有变量 private
console.log(tom.gender) //报错 因为 gender是受保护的变量 protected
// 两者的区别
class Student extends Person {
private constructor(name:string,age:number){
super(name,age)
console.log(this.gender)
}
static create(name:string,age:number){
return new Students(name,age)
}
}
// protected 修饰的变量可以在子类中访问
// 构造函数的访问修饰符 默认是 public 如果设置成private则不能在外部被实例化 也不能被继 承 如果此时想要实例化的话,则要在类中创建一个静态的方法去实例化
const jack = Student.create('jack',18)
// 对于private protected 也是不能在外部实例的 但是可以被继承
- 类的只读属性 //使用 readonly 可以类的属性成员 设置为只读属性 如果这个属性已经有 访问修饰符了 则应该跟在 修饰符的后面 对于只读属性 可以在类型声明的时候 直接在 = 后面 初始化 或者在 构造函数中初始化 在初始化后 只读属性 是不可以被修改的
class Person{
public name:string //公有成员 默认是公有
private age:number //私有变量
protected readonly gender:boolean
constructor|(name:string,age:number){
this.name = name
this.age = age
this.gender = true
}
sayHi(msg:string):void{
console.log(`I am ${this.name},${msg}`)
console.log(this.age)
}
}
- 类与接口
interface Eat{
eat (food:string):void
}
interface Run{
run (distance : number):void
}
class Person implements Eat,Run{
eat(food:string):void{
console.log(`优雅的进餐:${food}`)
}
run(distance:number){
console.log(`直立行走:${distance}`)
}
}
class Animal implements Eat,Run{
eat(food:string):void{
console.log(`呼噜呼噜的吃:${food}`)
}
run(distance:number){
console.log(`爬行:${distance}`)
}
}
// 以上两个类都有共有的特性 这种情况就相当于不同的类型实现了相同的接口
// 使用接口定义公共的能力
// 需要注意 让每个接口更细化 在接口中定义的能力不一定会同时存在,因此一个接口对应一个能力
- 抽象类 //抽象类和接口在某种程度上有点相似,他也是用来约束子类中必须要有某个成员 //不同的是 抽象类可以包含具体的实现 接口不包含具体的是实现 //较大的类目 使用抽象类 //定义方式 在class 前 加 abstract 抽象类只能被继承 不能被 new 去实例
abstract class Animal implements Eat,Run{
eat(food:string):void{
console.log(`呼噜呼噜的吃:${food}`)
}
abstract run(distance:number):void //抽象方法 不需要方法体
}
class Dog extends Animal{
run(distance:number):void{
console.log(`爬行:${distance}`)
}
}
const d = new Dog()
d.eat("谷歌")
d.run(500)
- 泛型
function createNumberArray(length:number,value:number):number[]{
const arr = Array<number>(length).fill(value) //使用Array时再定义类型
return arr
}
// 假如要定义一个string的数组 则上面的函数就不能用了 此时泛型就要上场了
function createArray<T>(length:number,value:T):T[]{
const arr = Array<T>(length).fill(value)
return arr
}
const res = createArray<string>(3,"TypeScript") //使用泛型将所需要的类型传递进去 能更好的复用代码