安装
npm install -g typescript
检测版本
tsc -v
让Vscode自动编译ts文件
1.通过命令创建tsconfig.json自动编译文件
tsc --init
2.tsconfig.json自动编译文件运行
typescript数据类型
1.数字类型 number
2.字符串类型 string
3.布尔值类型 blooean
当这些数据定义上这些类型后就不能进行更改数据类型
let num:number = 123
num='123' //ts会自动帮我们检测数据,如果不是之前声明的数据类型就会报错
4.数组类型
第一种定义方式
let 变量:数据类型[] = [根据该数据来的数组]
let aiqi:number[] = [1,2,3]
//这样定义数组里面的数据需为数字类型
第二种定义方式
let 变量名:Array<数据类型1,数据类型2> = [数据类型1的数据,数据类型2的数据]
//需要一一对应数据类型
5.元组类型
定义方式
let 变量名:[数据类型1,数据类型2,数据类型3] = [数据类型1的数据,数据类型2的数据,数据类型3的数据]
//元组这样定义的数据也需要一一对应好数据类型
6.枚举enum
定义方式
enum 变量名1{
数据一,
数据二,
数据三
}
let 变量名2:变量名1 = 变量名1.数据一
//enum中默认数据一是0,后面的数据是根据前面的数据加一,所以将数据一设为1,数据二设为3,那么数据三将是4
enum color = {
red = 2,
green,
bule
}
let aiqi1:string = color[3]
//这种会查找值3的值,并返回相应名字作为值
7.any类型
当你数据可能是后端返回不知啥类型数据可用any,但any就是不能判断你的数据类型,数据运用上报错它不会提示
let 变量名:any = 数据
当你不知道数组里面数据是什么类型就可用它定义数组
let 变量名:any[] = [随意数据类型数据1,随意数据类型数据2........]
8.void
表示没有任何类型,返回只能是null跟undefined
9.never
表示用不存在的类型
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
10.Object
类型断言
类型可以让数据不必受ts程序检测,告诉ts我已经检测过了,不用你了
第一种语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
第二种语法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length
类型推断
ts会在没有给定类型的变量给定类型
1.声明没有赋值的变量,类型为any
2.声明给定值,类型为该值的类型
接口interface
接口是对对象的属性或方法一种描述
interface aiqi ={
name:string,
age:number
}
let aiqison:aiqi={
name:'aiqison',
age:1
}
在接口中属性如果没有设置可选属性,用该接口描述的对象的属性就不能缺少,否则报错
1.可选属性
接口中属性设置了它,在用接口描述的对象的该属性可以不用写,不会报错
interface aiqi{
name?:string,
age:number
}
let aiqison:aiqi={
name:'aiqison'
}
//age属性设置可选属性,所以可以不用写
2.只读属性
设置该属性的属性1,用该接口描述的对象,只能在声明时,改动属性1的值,除此之外不能修改值。
interface aiqi{
readonly name:string,
age?:number
}
let aiqison:aiqi={
name:'aiqison'
}
aiqison.name='aiqifater' //此时ts会报错
3.函数类型
函数也可以使用接口来进行约束限制,但需要定义一个调用签名
interface aiqi{
(ai:string,qi:string):boolean //调用签名
}
const aiqison:aiqi = function(ai:string,qi:string):boolean{
return ai === qi
}
console.log(aiqison('ai','qi'))
4.类类型
在ts中也可使用,接口对进行约束
interface aiqi{
alert():any
}
class aiqison implements aiqi{
alert(){
console.log('aiqison')
}
}
const aiqisonson = new aiqison()
aiqisonson.alert()
类型也可以implements(实现)多个接口
interface aiqi1{
alert(){
console.log('aiqi')
}
}
interface aiqi2{
aiqiValue:string
}
class aiqison class aiqi1,aiqi2{
alert(){
console.log('aiqison')
}
aiqiValue = 2
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
}
const aiqisonson = new aiqison(2)
console.log(aiqisonson.aiqiValue)
接口继承接口
interface aiqif{
alert():any
}
interface aiqim{
aiqiValue:number
}
interface aiqison extends aiqif,aiqim{
}
class aiqisonson implements aiqison{
alert(){
console.log(1);
}
aiqiValue:number = 1
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
}
const aiqisss = new aiqisonson(1)
console.log(aiqisss.aiqiValue);
类
class aiqi{
aiqiValue:number
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
aiqiF(aiqi:number){
return aiqi = this.aiqiValue+1
}
}
class aiqison extends aiqi{
constructor(aiqiValue:number){
super(aiqiValue)
}
aiqiF(aiqi:number){
return aiqi = this.aiqiValue+aiqi
}
}
const aiqiss = new aiqison(111)
console.log(aiqiss.aiqiValue) //111
console.log(aiqiss.aiqiF(111)) //222
1.继承
class aiqi{
aiqiValue:number
aiqiF(aiqiFValue:number):number{
console.log('======')
return aiqiFValue
}
}
class aiqison extends aiqi{
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
aiqiF():number{
super.aiqiF(1111)
return 1
}
}
const aiqiss = new aiqison()
console.log(aiqiss.aiqiF())
继承的子类,也可称为派生类,在派生类中包含一个构造函数,它必须调用super对父类定义的属性进行继承,才能用this对这个属性进行调用,如果想要调用父类函数的方法必须使用super.方法(),才能进行调用
2.修饰符
公共修饰符public
它修饰的属性或方法,无论是子类或实例化的对象都可以修改或访问它修饰的属性或方法
class aiqi{
public aiqiValue:number
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
public aiqiF(){
return this.aiqiValue
}
}
class aiqison extends aiqi{
constructor(aiqiValue:number){
super(aiqiValue)
}
aiqiF():number{
super.aiqiF()
return 1
}
}
const aiqiss = new aiqison(111)
aiqiss.aiqiValue = 22222
console.log(aiqiss.aiqiValue)
私有修饰符private
它修饰的属性或方法,跟public相仿,无论是子类或实例化的对象都不可以修改或访问它修饰的属性或方法
class aiqi{
private aiqiValue:number
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
private aiqiF(){
return this.aiqiValue
}
}
class aiqison extends aiqi{
constructor(aiqiValue:number){
super(aiqiValue)
}
aiqiF():number{
console.log(111111111)
super.aiqiF() //报错
return 1
}
}
const aiqiss = new aiqison(111)
aiqiss.aiqiValue = 22222 //报错
console.log(aiqiss.aiqiValue) //报错
console.log(aiqiss.aiqiF())
3.受保护修饰符protected
它修饰的属性或方法,子类或实例化的对象只能对其进行访问,不能进行修改
class aiqi{
protected aiqiValue:number
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
protected aiqiF(){
return this.aiqiValue
}
}
class aiqison extends aiqi{
constructor(aiqiValue:number){
super(aiqiValue)
}
aiqiF():number{
console.log(111111111)
super.aiqiF()
return 1
}
}
const aiqiss = new aiqison(111)
aiqiss.aiqiValue = 22222 //报错
console.log(aiqiss.aiqiValue) //报错
console.log(aiqiss.aiqiF())
只读属性readonly
readonly跟protected类型只能读不能修改(但是还是有点不同的,可以看看以下代码)
readonly的
class aiqi{
readonly aiqiValue:number
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
protected aiqiF(){
return this.aiqiValue
}
}
class aiqison extends aiqi{
constructor(aiqiValue:number){
super(aiqiValue)
}
aiqiF():number{
console.log(111111111)
super.aiqiF()
return 1
}
}
const aiqiss = new aiqison(111)
aiqiss.aiqiValue = 22222 //报错
console.log(aiqiss.aiqiValue)
console.log(aiqiss.aiqiF())
protected的
class aiqi{
protected aiqiValue:number
constructor(aiqiValue:number){
this.aiqiValue = aiqiValue
}
protected aiqiF(){
return this.aiqiValue
}
}
class aiqison extends aiqi{
constructor(aiqiValue:number){
super(aiqiValue)
}
aiqiF():number{
console.log(111111111)
super.aiqiF()
return 1
}
}
const aiqiss = new aiqison(111)
aiqiss.aiqiValue = 22222 //报错
console.log(aiqiss.aiqiValue) //报错
console.log(aiqiss.aiqiF())
总结protected修饰的属性进行修改后,连访问都不能访问,但readonly修改后却依然进行访问
参数属性
可以用参数属性来初始化属性
class aiqi {
constructor(readonly aiqiValue:number){
this.aiqiValue = aiqiValue
}
}
class aiqi2 {
constructor(public aiqiValue:number){
this.aiqiValue = aiqiValue
}
}
3.存取器
class aiqi{
firstName:string = '111'
lastName:string = '222'
constructor(aiqiV1:string,aiqiV2:string){
this.firstName = aiqiV1
this.lastName = aiqiV2
}
get fullName(){
return this.firstName + this.lastName
}
set fullName(Value:string){
const name = Value.split('-')
console.log(11111111111);
this.firstName = name[0]
this.lastName = name[1]
}
}
const aiqison = new aiqi('zeng','yongfeng')
//调用get
console.log(aiqison.fullName);
//调用set
aiqison.fullName='kong-yuqi'
console.log(aiqison.fullName)
4.静态属性
class aiqi {
static aiqiV1:string = '1111111111111' //类对象静态属性(实例化对象不能访问或修改)
aiqiV2:string = '2222222222222222' //类的实例化对象属性
}
const aiqison = new aiqi()
console.log(aiqi.aiqiV1)
console.log(aiqison.aiqiV2)
5.抽象类abstract
抽象类不能直接实例化对象,通过继承抽象类的类,可以实例化,abstract关键字不仅可以定义类,还可以定义抽象类里面的方法
abstract class aiqi{
abstract aiqiF():number
}
class aiqison extends aiqi{
aiqiF():number{
console.log('111111111')
return 1
}
}
函数
function aiqi1(aiqiV1:number,aiqiV2:string){
return 111111
}
let aiqi2 = (aiqiV1:string,aiqiV2:number){
return 222222
}
1.默认参数和可选参数
function aiqi(aiqiV1:number=1,aiqiV2?:string){
return 111111111111111111111111
}
2.剩余参数
可以 …+自定义名字 作为一个数组来接受剩余参数
function aiqi(aiqiV1,...aiqiV2){
console.log(aiqiV1,...aiqiV2)
}
3.函数重载
函数重载:根据参数类型不同,返回不同数据
function aiqi(aV1:string,aV2:string):string
function aiqi(aV1:number,aV2:number):number
function aiqi(aV1:string|number,aV2:string|number):string | number{
if(typeof aV1 === 'string' && typeof aV2 === 'string'){
return aV2+aV1
}else if(typeof aV1 === 'number' && typeof aV2 === 'number'){
return aV2+aV1
}
return (aV1 as number) + (aV2 as number)
}
console.log(aiqi(1,2))
/*
函数重载: 函数名相同, 而形参不同的多个函数
需求: 我们有一个add函数,它可以接收2个string类型的参数进行拼接,也可以接收2个number类型的参数进行相加
*/
// 重载函数声明
function add(x: string, y: string): string
function add(x: number, y: number): number
// 定义函数实现
function add(x: string | number, y: string | number): string | number {
// 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 x + y
if (typeof x === 'string' && typeof y === 'string') {
return x + y
} else if (typeof x === 'number' && typeof y === 'number') {
return x + y
}
}
console.log(add(1, 2))
console.log(add('a', 'b'))
// console.log(add(1, 'a')) // error
泛型
在定义东西时,先不给类型,等在使用再给类型
1.函数泛型
function aiqi<T>(aV1: T, aV2: number) {
const aiqiValue: Array<T> = []
for (let i = 0; i < aV2; i++) {
aiqiValue.push(aV1)
}
return aiqiValue
}
console.log(aiqi<number>(1, 1000));
2.多个泛型的函数
function aiqi<T,K>(a:T,b:K):[T,K]{
return [a,b]
}
console.log(aiqi<number,string>(1,'1'));
3.类型接口
interface IbaseCRUD<T> {
data: T[]
add: (t: T) => void
getById: (id: number) => T
}
class User {
id?: number //id主键自增
name: string //姓名
age: number //年龄
constructor(name, age) {
this.name = name
this.age = age
}
}
class UserCRUD implements IbaseCRUD<User> {
data: User[] = []
add(user: User): void {
user = { ...user, id: Date.now() }
this.data.push(user)
console.log('保存user', user.id)
}
getById(id: number): User {
return this.data.find(item => item.id === id)
}
}
const userCRUD = new UserCRUD()
userCRUD.add(new User('tom', 12))
userCRUD.add(new User('tom2', 13))
console.log(userCRUD.data)
4.泛型类
class GenericNumber<T> {
zeroValue: T
add: (x: T, y: T) => T
}
let myGenericNumber = new GenericNumber<number>()
myGenericNumber.zeroValue = 0
myGenericNumber.add = function(x, y) {
return x + y
}
let myGenericString = new GenericNumber<string>()
myGenericString.zeroValue = 'abc'
myGenericString.add = function(x, y) {
return x + y
}
console.log(myGenericString.add(myGenericString.zeroValue, 'test'))
console.log(myGenericNumber.add(myGenericNumber.zeroValue, 12))
5.泛型约束
// 没有泛型约束
function fn<T>(x: T): void {
// console.log(x.length) // error
}
interface Lengthwise {
length: number
}
// 指定泛型约束
function fn2<T extends Lengthwise>(x: T): void {
console.log(x.length)
}
泛型约束是继承接口中属性类型来进行约束的
声明文件(这个不重要,因为平时脚手架开发,已经帮我们弄好了)
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能
什么是声明语句
假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过
但是在 ts 中,编译器并不知道 $ 或 jQuery 是什么东西
/*
当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
声明语句: 如果需要ts对新的语法进行检查, 需要要加载了对应的类型说明代码
declare var jQuery: (selector: string) => any;
声明文件: 把声明语句放到一个单独的文件(jQuery.d.ts)中, ts会自动解析到项目中所有声明文件
下载声明文件: npm install @types/jquery --save-dev
*/
jQuery('#foo')
// ERROR: Cannot find name 'jQuery'.
这时,我们需要使用 declare var 来定义它的类型
declare var jQuery: (selector: string) => any
jQuery(’#foo’)
declare var 并没有真的定义一个变量,只是定义了全局变量 jQuery 的类型,仅仅会用于编译时的检查,在编译结果中会被删除。它编译结果是:
jQuery(’#foo’)
一般声明文件都会单独写成一个 xxx.d.ts 文件
创建 01_jQuery.d.ts, 将声明语句定义其中, TS 编译器会扫描并加载项目中所有的 TS 声明文件
declare var jQuery: (selector: string) => any
很多的第三方库都定义了对应的声明文件库, 库文件名一般为 @types/xxx, 可以在 https://www.npmjs.com/package/package 进行搜索
有的第三库在下载时就会自动下载对应的声明文件库(比如: webpack),有的可能需要单独下载(比如 jQuery/react)
内置对象
js的内置对象在ts也可以照样使用