文章目录
- 1:基础类型
- 数值型 number
- 字符串类型 string
- 布尔类型 boolean
- 数组类型 Array
- 元组 Tuple
- 任意类型 any
- void:与any类型相反,表示没有类型
- null 、undefined类型
- never类型
- 枚举类型
- 类型断言
- 类型推论|类型别名
- 2:接口
- 3:类(不咋用)
- static 静态属性 和 静态方法
- 在类中使用接口
- 抽象类
- 4:函数
- 接口定义函数
- 函数重载
- 5:联合类型 交叉类型
- 6:泛型
- 7.命名空间
TypeScript:
1:基础类型
声明格式:
let 变量名:变量类型 = 赋值内容
数值型 number
let num:number = 123//支持十进制和十六进制字面量
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
字符串类型 string
let str:string = '字符串'
布尔类型 boolean
let bool: boolean = false
数组类型 Array
//数组有两种声明方式
let arr: number[] = [1,2,3]
let arr2:Array<number> = [1,2,3] //这里规范了number类型,那么数组内容就必须是number类型//数组内容有多种类型
let arr3:(number | string)[] = [1,'nihao']
let arr4:Array<number | boolean> = [true,1] //在声明的时候使用联合类型
元组 Tuple
TS的新概念:元组是固定数量的不同类型的元素的组合
元组变异的数组,其中的元素类型可以是不同的,而且数量固定,好处在于可以把多个元素作为一个单元传递。
let tuple:[number,string]
tuple =['nihao',1] //Error
tuple =[1,'nihao'] //需要与声明时规范的类型一一对应//越界时,新增的内容需要是规范的类型中的某一个
tuple.push(true) //error 报错
tuple.push("sss") // 可以//注意 若声明时添加了readonly->只读元组
let tuple2:readonly [number,string] = [111,'aaa']
任意类型 any
let aaa:any
aaa=1
aaa="123"
aaa=false
void:与any类型相反,表示没有类型
一般用于没有返回值的函数,使用void声明的变量没有用处,void类型的变量只能赋值null 、undefined
function fn():void{console.log("This is my warning message");
}
let vv:void = null
let vvv:void= undefined
null 、undefined类型
null 、undefined是所有类型的子类型,表示可以给一个使用number类型的变量赋值null 、undefined
let u: undefined = undefined;
let n: null = null;
never类型
表示用不可能的值,never是任意类型的子类型,但任意类型都不能是never的子类型,任意类型的值都不能赋给never类型的变量除了never类型本身。
//抛出一个值
const errorFunc = (message: string): never => {throw new Error(message);
}//死循环
const infinteFunc = (): never => {while (true) { }
}
枚举类型
枚举类型的声明方式和上述的类型有区别:
//enum 变量名{
// 枚举值,枚举值
//}enum Type {red,blue,green
}
Type.red // 0
Type.blue // 1
Type.green // 2// 枚举值会自增
enum Type2 {red,blue=6,green // 0 6 7
}//枚举值也可以是字符串,
enum Types{Red = 'red',Green = 'green',BLue = 'blue'
}//异构枚举值:表示枚举值既有字符串又有数字
enum Types{No = "No",Yes = 1,
}//接口枚举
enum Types {yyds,dddd}interface A {red:Types.yyds}let arr:A ={red:Types.yyds}
let arr2:A ={red:"12222"} //报错//const 声明的枚举会被编译成常量
const enum ttt{aa,aaa,bb
}//反向映射enum T {fail
} let n = T.fail //0
let nn = T[n] // 'fail'
类型断言
语法:
<类型>变量 || (变量名 as 类型)
//js的一个函数获取传来的内容的length
const getLength = target => {if (target.length || target.length == 0) {return target.length} else {return target.toString().length}
}
//ts
//这样写是会报错的类型“string | number”上不存在属性“length”。
//类型“number”上不存在属性“length”
const tsGetLength= (target:(string | number)) =>{if (target.length || target.length == 0) {return target.length} else {return target.toString().length}
}//类型断言:
//<类型>变量 || (变量名 as 类型)
const tsGetLengthaa= (target:(string | number)) =>{if ((<string>target).length || (target as string).length == 0) {return (target as string).length} else {return target.toString().length}}
类型推论|类型别名
//类型推论
let aa = "你好" //这样定义的变量aa,ts会推论出aa为string类型
aa=123 //error 这样就会报错 不能吧number赋值给string类型let bb //这时给bb赋值的是null类型
bb = [] //合法
bb = {} //合法
bb = 'hahha' //合法
//类型别名
//let str:string = "你好"
type s = string //定义一个string类型的类型别名
let str:s = "你好"type T = string | number
let num:T=123
let str1:T="你好"
2:接口
在TS中定义对象的方式要用关键字interface,
接口用来定义一种约束,让数据的结构满足约束的格式。
语法:
interface 接口名 {}
const getFullNameTS = ({fristName,lastName}:{fristName:string,lastName:string}) :string=>{return `${fristName} ${lastName}`
}//简化
interface nameRule{fristName:string,lastName:string
}
const getFullNameTS = ({fristName,lastName}:nameRule):string=>{fristName:string,lastName:string}) :string=>{
}
//使用接口定义对象
interface Rule{name:string,age:number
}let P:Rule={name:"ddd",age:123
}//如果此时省略不传,是会报错的
//可选属性 可算操作符 ?
interface Rule{name:string,age?:number
}let P:Rule={name:"ddd",
}
//只读属性
interface Rule{readonly name:string, //此时name为只读属性age?:number
}
let P:Rule={name:"ddd",
}
P.name = "aaa" //报错
//任意属性
interface Rule{readonly name:string, //此时name为只读属性age?:number[propName:string]:any //索引签名
}//这样声明后定义对象时传递这里没有约束的规则也不会报错let P:Rule={name:"ddd",sex:"man"
}
//继承接口
interface Rule{readonly name:string, //此时name为只读属性age?:number[propName:string]:any//索引签名
}//这样声明后定义对象时传递这里没有约束的规则也不会报错interface Rule2 extends Rule{ // extends 继承的接口名,继承的接口名fn():void
}//这样声明后定义对象时传递这里没有约束的规则也不会报错
3:类(不咋用)
//simple class
class Animal{name:string //在TypeScript是不允许直接在constructor 定义变量的 需要在constructor上面先声明constructor(name:string) {this.name = nameconsole.log("a "+this.name);},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);
dog.bark();//公共,私有与受保护的修饰符 public private protected
//上述name字段时class中的变量,修饰符省略时默认为 public
//public表示类的内部外部都可以访问
//private 修饰符 代表定义的变量私有的只能在内部访问 不能在外部访问 (继承的子类 不能访问)
//protected 修饰符 代表定义的变量私有的只能在内部和继承的子类中访问 不能在外部访问
static 静态属性 和 静态方法
//static 定义的属性和方法 不可以通过this 去访问 只能通过类名去调用
class A {name:stringconstructor(name:string) {this.name = name}static aa:string = "常量"static run():void{this.stop()//如果两个函数都是static 静态的是可以通过this互相调用}static stop():void{//如果两个函数都是static 静态的是可以通过this互相调用}
}
A.aa //diaoyong
A.run()
在类中使用接口
// 使用implements关键字
interface C {name:string
}class A implements C{name:stringconstructor({name}:C) {this.name = name}static aa :string = "常量"staticrun ():string
}
抽象类
//抽象类 需要使用abstract
interface C {name:string
}
abstract class A implements C{name:stringconstructor(name:string) {this.name = name}static aa :string = "常量"abstract run ():string //这里不能写具体分方法,定义的抽象方法必须在派生类实现
}
//派生类
interface C {name:string
}
// 继承抽象类,
class B extends A implements C{constructor({name}:C){super(name)}run(): string {return this.name}
}
let b = new B({name:"不好"})
B.aa
console.log('BBBB',b.run(),B.aa);
4:函数
//simple example
const fn = (name:string,age:number):void=>{console.log(`age:${age},name:${name}`);
}fn('你好',100)//需要与形参上定义的一一对应//默认值
const fn = (name:string = '哈哈'):string=>{return name
}fn("hhahah") //hhahah
fn() // 哈哈
接口定义函数
interface rule {name:string,age?:number,[propName:string]:any
}const fn = ({name,age}:rule):void=>{console.log(`age:${age},name:${name}`);
}fn({name:"aa",age:23})
函数重载
重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。
如果参数类型不同,则参数类型应设置为 any。
参数数量不同你可以将不同的参数设置为可选。
function fn(params: number): void function fn(params: string, params2: number): voidfunction fn(params: any, params2?: any): void {console.log(params)console.log(params2)
}fn(123)
fn('123',456)
5:联合类型 交叉类型
let phone:number = 183555225222
//此时需要支持座机号,座机号码一般都是010-2293923
//使用联合类型 |
let phone:number | string = '010-0101010' || 183555225222 //交叉类型 &
interface Person {name:string,age:number
}interface Man {sex:string
}const sss = (man:(Man & Person)):void=>{console.log(man.age)console.log(man.sex)console.log(man.name)
}sss({name:"xiaosong",age:12,sex:"man"
})
6:泛型
定义函数、类的时候不预先指定类型,在使用的时候再指定类型
//假设存在一个这样的函数 输出a,b参数组成的数组,
function num(a:number,b:number):Array<number>{ 输入number类型的数据返回一个number类型的数组return [a,b]
}console.log(num(1,2));
num('1','2')//这样TS就会报错//使用泛型
//定义时类型时不明确的
function change<T>(params1:T,params2:T):Array<T>{return [params1,params2]
}//使用时需要明确类型
change<number>(1,2)
change<string>('1','2') // change('1','2')编译器会根据传入的参数自动地确认类型
6.1:泛型约束
function prop<T,K extends keyof T>(obj:T,key:K){ //K extends keyof T 约束了T的类型return obj[key]
}
7.命名空间
假设存在两个文件 index1.ts 、 index2.ts
// index1.ts 中定义了一个变量a
const a = 123
// index2.ts 中也定义了一个变量a
const a = 456
这时index2.ts声明的变量会报错,这样定义的变量是全局的,const定义的变量具有唯一性。
解决:
方法一
//index2.ts 中使用export关键字,将index2.ts文件中的a定义为局部变量
export const a = 456
方法二,使用命名空间
//index1.ts中:
namespace A {export const a = 123
}
//index2.ts中:
namespace B {export const a = 3455
}//使用时:
console.log(A.a)
console.log(B.a)
嵌套命名空间:
namespace a {export namespace b {export class Vue {parameters: stringconstructor(parameters: string) {this.parameters = parameters}}}
}let v = a.b.Vue
new v('1')
抽离命名空间
//index.ts内容
export namespace VVV {export a="抽离"
}
//假设使用时的文件是合index.ts平级
import {VVV} form './index.ts'
console.log(VVV) // 打印出来 : {a:"抽离"}
简化命名空间
namespace A {export namespace B {export vvv = 12345}
}import temp = A.B.vvv
console.log(temp)
//这样就可以直接打印出vvv的值
合并命名空间
//重名的命名空间会合并
namespace A {export const a = 123
}
namespace A {export const b = 123
}
//那么 A这个命名空间里就存在a、b两个变量