ts的安装
npm install -g typescript //全局安装
安装完成后控制台 输入 ==tsc -v === 有以下输出说明安装成
基础类型写法
let numb: number = 123 //数字类型
let myStr: string = '123456' //string 类型
let myBl: boolean = true //布尔类型
let u: undefined = undefined //undefined
let n: null = null //undefined
// undefined 和 null 是任意类型的子类 , 所以下面写法不会报错
let num: number = undefined
// any 类型
// any 类型就是任意类型都可以,这个就失去了对类型的约束,跟js一样了,建议不使用
let isAny: any = '123'
isAny = 123
isAny.nub = null
字面量
//字面量 |:
let a: '你好' | '你也好' //a的值如果不是其中的一个就会报错
a = '你好'
a = '你也好'
unknown类型
//unknown类型跟any类型非常的像,但是unknown类型必须要经过验证才能使用,二 any类型数据不需要
let score: unknown = 5
// 这个时候会报错
console.log(score * 2);
// 那我们要验证 一下类型 就能使用 unknown类型的数据了
if (typeof score === 'number') {
console.log(score * 2)
}
数组
let arr: number[] = [1, 2, 3,] //数字类型的数组,知道是数字 不能是其他
let arrs: Array<string> = ['1', '3', '哈哈哈'] //这样写法也可以
二维数组
let arr2: number[][] = [[1, 3, 4, 5, 6]]
对象类型数组
// 对象类型的数组
let objArr: { name: string, age: number }[] = [{ name: '张三', age: 24 }]
往数组中push不同类型数组也是会报错
// 往数组里面push不同类型的数据 也是会报错的
let num: number[] = [1, 3, 4, 5, 6]
num.push('你好') //error 报错
数组也可以是any类型
// 数组也可以是any类型
let anyArr: any[] = [1, 3, 'hello', { name: '李四', age: 35 }]
对象
// 对象
// 属性后面加?表示可选参数,可以加可以不加
let obj:{name:string,age:number,address?:string}
// 写了address也对
obj = { name: '李雷', age: 23, address: '中国' }
// 不写 address也可以,
obj = { name: '李雷', age: 23 }
// 如果我希望 一个对象里必须要有 name属性,其他的可有可无
//proName是形参 可以传任意,类型必须是自己定义的类型
let a: { name: string, [proName: string]: any }
a={name:'lili'}
a = { name: 'hah', address: '中国',height:178 }
函数
// 函数
/*
函数的可选参数也是参数后面加 ? 号
可以参数后面不能再跟参数
*/
//第一种写法
function add(x:number,y:number,z?:number):number {
return x+y
}
//传3个参数
add(1, 2, 3)
add(1,2) //传两个参数
第二种写法
// 第二种写法
let merge: (x: number, y: number, z?: number) => number = function (x: number, y: number, z?: number): number{
return x+y
}
第三种箭头函数写法
// 换成箭头函数的写法
let add2: (x: number, y: number, z?: number) => number = (x: number, y: number, z?: number): number => {
return x+y
}
推荐写法
// 推荐这个写法,比较简便点
function fun(x: number, y: number): number{
return x + y
}
函数的各种返回值写法
// 如果函数没有返回值就是 void
function fn(x: number, y: number): void{
console.log(x+y)
}
// 如果是没有返回值的函数加了返回值就会报错
// 函数返回的是数组
function fnArr(x: number, y: number): number[]{
return [x,123]
}
// 函数返回的是对象
function fnObj(x: number, y: number): { age: number }{
return { age: x }
}
// 返回值是函数
function _fn(a: number): (b: number) => number{
return function (b: number) {
return a + b
}
}
类型别名
// 类型别名
type a = number
let b: a = 123456
// 类型别名定义函数
type add = (x: number) => number
let add2: add = (x: number): number => x
function fn(x: string, y: number): boolean {
return false
}
let fn2:(x: number)=> string = function(x: number) : string{
return 'hah'
}
联合类型
// 联合类型
// 联合类型使用 | 分割每个类型
// 联合类型中 函数必须要用括号包起来
let fc: number | string | boolean | ((x: number) => number) | string[]
// 这样 fc可以是上面定义的其中一种
fc = false
fc = 'hello'
fc = ['h', 'e', 'l', 'l']
fc = function (x: number) {
//函数类型
return x
}
fc(5) //调用
/*所以我们之前定义存储不同数据数组的时候,也可以使
用联合类型
*/
const arr: (number | string)[] = [1, 'string', 2, 'true']
/**
特殊的,如果访问联合类型的属性或方法:
当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时
候
我们只能访问此联合类型的所有类型里共有的属性或方法:
*/
function getLength(sem: string | number): number {
return sem.length //这里就会报错,因为 length不是string和number共有的属性
}
function getstr(sem: string | number): string {
return sem.toString() //这样访问是正确的,toString()是他们共有的属性
}
接口 interface
在typescript中我们可以使用 接口(interface)来定义对象
**接口其实就是用来定义一个模板,以后 声明的对象 都要按照这个模板来定义**
// 接口
interface girl {
height: number
like: boolean
money?: number //可选属性
readonly age: number //只读属性,如果修改只读属性就会报错
}
interface person {
name: string
money: number
like: boolean
hobby: string[]
make: () => void //函数无返回值
girlFriend: girl //对象 要与 接口girl一样
}
// 实现接口
let zs: person = {
name: '张三',
money: 100,
like: true,
hobby: ['唱歌', '跳舞'],
make: () => {},
girlFriend: {
height: 165,
like: true,
money: 1000,
age: 18,
},
}
console.log(zs)
zs.girlFriend.age = 28 //更改只读属性会报错
有时候我们需要一个接口有任意属性 我们要这么写
interface person{
name: string,
age?: number,
[propName:string]:any, //任意属性定义
}
// 实例
let tom: person = {
name: 'tom',
age: 25,
gender:'male'
}
需要注意的是,一旦定义了任意属性,那么确定属性和
可选属性的类型都必须是它的类型的子集:
一个接口中只能定义一个任意属性。如果接口中有多个
类型的属性,则可以在任意属性中使用联合类型
interface Person{
name: string,
//age?:number, //注意使用了任意属性以后,如果任意属性不是any类型,可选属性就会报错
[propName:string]:number|string, //任意属性定义
}
// 实例
let tom: Person = {
name: 'tom',
age: 15,
gender: "男",
height:180
}
接口的继承
// 接口的继承
interface Person{
name: string,
age:number
}
// 接口继承,要完全继承Person是属性
interface BoyFriend extends Person{
money: number,
hobby:string[]
}
// 创建对象的时候必须要把继承的属性也要创建
let xm: BoyFriend = {
name: 'xm',
age: 34,
money: 2000,
hobby:['cg','tw']
}
一个接口可以被多个接口继承,同样,一个接口也可以
继承多个接口,多个接口用逗号隔开
// 多个接口的继承
interface Animals{
name:string
}
interface Friends{
like:string
}
// 继承多个接口,用逗号分开
interface Dog extends Animals, Friends{
name: string,
color:string
}
const dog: Dog = {
name: '狗',
like: 'sleep',
color:'黄色'
}
接口中使用联合类型
// 接口中也可以使用联合类型
interface Person{
name: string,
like: string | string[] | (() => string)
}
// 接口使用联合类型实现
let xm: Person = {
name: 'xm',
// like: '足球',
// like: ['篮球,足球'],
like: () => '就是玩'
}
接口定义数组
// 接口定义数组
interface arr{
// 这里[] 内是数组的下表索引,必须要是number类型
[index:number]:string
}
// 实现
let arrList: arr = ['1', '3', '4']
类型断言
类型断言就是我明确的知道我这个数据肯定是字符串,
告诉编译器你不用检测他了。
语法
值 as 类型
联合类型用途
1.将一个联合类型断言为其中一个类型
**当 TypeScript 不确定一个联合类型的变量到底是哪个类
型的时候,我们只能访问此联合类型的所有类型中共有
的属性或方法
**
// 类型断言
interface Cat{
name: string,
run():void
}
interface Fist{
name: string,
swin():void
}
function getName(animal: Cat | Fist) {
return animal.name //只能访问共有属性
}
function getAs(animal: Cat | Fist) {
// 使用断言 把 animal断言成 Fist就能使用它的 函数方法
if (typeof (animal as Fist).swin === "function") {
//这样子 animal.swin 就不会报错了
return true
} else {
return false
}
}
需要注意的是,类型断言只能够「欺骗」TypeScript 编
译器,无法避免运行时的错误,反而滥用类型断言可能
会导致运行时错误:
使用类型断言覆盖其类型推断
/**
案例
使用类型断言(as关键字) 来覆盖其类型推断
*/
let student = {}
// let student:{}
student.name = "jack" //报错 类型“{}”上不存在属性“name”
// 使用类型断言 as 来覆盖, 这个时候就需要有一个接口
interface Person{
name:string
}
let sdt = {} as Person
sdt.name = "sdt" //这样就不会报错
将父类断言成子类
// 将父类断言成子类
class Student{
make() {
console.log('i can like money')
}
}
class xm extends Student {
run() {
console.log('i can run')
}
}
let a = new Student();
a.run() // 类型“Student”上不存在属性“run”
(a as xm).run() // 断言成子类,正确
非空断言
let num: number | undefined | null
// 在num后面添加非空断言符 ! ,以此来断言num是非空值
num!.toFixed()
// 这种写法的意思是,如果num不为空就执行 toFixed()这个方法
num?.toFixed()
和其他类型断言一样, 这种断言只会让TypeScript不报错, 但不会
改变代码运行时的行为
简单说就是在编译后运行时如果num变量的值是null 或
undefined ,JavaScript依然会报错
元祖(可以存放多种类似的数组)
**我们知道数组中元素的数据类型都一般是相同的(any[] 类型的
数组可以不同)
如果存储的元素数据类型不同,则需要使用元组。
元组中允许存储不同类型的元素,元组可以作为参数传递给函
数。元祖的数量是固定的
**
let arr: [string, number] = ['18829', 124];
// const arr1: [number, string] = ['sein', 2334] //error 这个时候数组值的位置类型对不上就报错
// 当添加越界元素的时候,元祖的类型会被限制为元祖中每个类型的联合类型
arr.push(123)
arr.push('hahah')
arr.push(true) //这里就报错了,不是元祖中定义的两个类型
枚举
// 枚举
enum Arr {
one=1,two,three,foru
}
// 如果没指定 one=1 的时候 默认是从 0 开始,后面自动递增
console.log(Arr.one === 1); //true
console.log(Arr.three === 3); //true
// 它们的值是可以反向映射的
console.log(Arr['two'] === 2); //true
// 可以收到给赋值
enum xm { a = 1, b, c, d = 8, e }
// 未手动赋值的枚举项会接着上一个枚举项递增。
console.log(xm.a === 1);//true
console.log(xm.b === 2);//true
泛型
泛型(Generics)是指在定义函数、接口或类的时候,
不预先指定具体的类型,而在使用的时候再指定类型的
一种特性。
有时候我们想函数传入的值跟返回的值是同类型,那么我们就需要使用泛型来精减代码量
// 函数中使用泛型
function indentity<T>(arg:T): T{
return arg
}
indentity(500) //正确
我们给identity添加了类型变量T。 T帮助我们捕获用户
传入的类型(比如:number),之后我们就可以使用
这个类型。 之后我们再次使用了 T当做返回值类型。现
在我们可以知道参数类型与返回值类型是相同的了。 这
允许我们跟踪函数里使用的类型的信息。
我们把这个版本的identity函数叫做泛型,因为它可以适
用于多个类型。 不同于使用 any,它不会丢失信息,像
第一个例子那像保持准确性,传入数值类型并返回数值
类型。
对象接口中使用泛型
// 对象接口中使用泛型
interface Person<T>{
name: string,
age:T
}
const xiong: Person<string> = {
name: 'xiong',
age: '28',
// age:28 // 报错
}
class 类
// class 类
class Person{
name: string
age: number
constructor(name:string,age:number) {
this.name = name
this.age=age
}
sleep() {
console.log('我睡一会觉')
}
}
const xiong = new Person('xiong', 18)
console.log(xiong);
// 继承
class long extends Person{
hobby: string[]
sex:string
constructor(name: string, age: number, sex: string) {
// 子类的构造器必须主动调用父类的构造器super(),这样才能继承
super(name, age)
this.sex = sex
}
sleep(): void {//重写,子类的方法如果跟父类一样,就会吧父类的覆盖
console.log('我好困')
}
}
访问修饰符
public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的
class Animal{
public name: string
private age: number //private 私有的不能在申明它的类的外部访问
protected color:string //protected修饰是可以被子类中访问,但是还是不能在外部访问
public constructor(name:string,age:number,color:string) { //public是可以被访问的
this.name = name
this.age = age
this.color=color
}
}
const dog = new Animal('狗', 2,'黄色')
//console.log(dog.age) //这里访问私有属性,已经报错了,子类中也是不能访问的
抽象类(abstract)
抽象类是不允许被实例化的