// 建议你每行代码都都敲一遍
TypeScript 中最基本的数据类型包括布尔、数字、字符串、null、undefined
let courseName:string = "学习"
let price:number = 129
// price = '12'
let isOnline:boolean = true
let courseSales:undefined
let timer:null = null
let me:[string,number] =['张三',12]
// me[0]= 1
当你不确定某个变量是什么类型时,你可以使用 any 作为这个变量的类型
let anThing
let anyCourse:any =1
anyCourse='aaa'
// console.log(anyCourse)
使用 enum 去定义枚举类型,这样可以把类型限制在指定的场景之内。
enum 课程评分 {好,非常好,嘎嘎好}
// console.log(课程评分['好']===0)
let scores = [课程评分['好'],课程评分['非常好'],课程评分['嘎嘎好']]
// console.log(scores)
let course1:string|number ="111"
course1=123
// course1=false
通过这些基础类型,通过组合的方式组合出新的类型,最常见的组合方式就是使用 | 实现类型联合。
type courseScore = 'good'|'very good'|'gaga good'
// let score1:courseScore ='111'
let score1:courseScore ='good'
通过 interface 接口可以定义对象的类型限制
interface geekTime{
name:string,
price:number,
user:string,
pic?:string|boolean,//?设置为可选属性
readonly address:string
}
let vueCourse:geekTime={
name:"vue",
price:123,
user:"students",
address:"time.geekTime.org"
}
vueCourse.pic = false
// vueCourse.address = "1222"
然后我们学一下函数的类型限制。其实函数的定义,参数和返回值本质上也是变量的概念,都可以进行类型的定义。
function add(a:number,b:number):number{
return a+b
}
let add1 = add(4,6)
// console.log(add1)
我们也可以使用变量的方式去定义函数,直接使用 (参数类型) => 返回值类型的语法去定义 add1 的变量类型,但是这样写出来的代码可读性稍差一些,我更建议你使用 type 或者 interface 关键字去定义函数的类型。
let add2:(a:number,b:number)=>number = function(x:number,y:number):number{
return x+y
}
type addType = (a:number,b:number)=>number
let add3:addType = function (x:number,y:number):number{
return x+y
}
interface addType1{
(a:number,b:number):number
}
let add4 :addType1 = function (x:number,y:number):number{
return x+y
}
如果你的函数本来就支持多个类型的参数,下面的代码中 reverse 函数既支持数字也支持字符串。我们的要求是如果参数是数字,返回值也要是数字,参数是字符串返回值也只能是字符串,所以参数和返回值都用 number|string 就没法精确地限制这个需求。我们需要使用函数重载的方式,定义多个函数的输入值和返回值类型,更精确地限制函数的类型。
function reverse(x:number):number
function reverse(x:string):string
function reverse(x:number|string):number|string|void{
if(typeof x ==="number"){
return Number(x.toString().split('').reverse().join(''))
}else if( typeof x==="string"){
return x.split('').reverse().join('')
}
}
// console.log(reverse("123"))
// console.log(reverse(456))
日常开发中有很多浏览器上的变量和属性,这些怎么限制类型呢?关于宿主环境里的类型,TypeScript 全部都给我们提供了,我们可以直接在代码中书写:Window 是 window 的类型,HTMLElement 是 dom 元素类型,NodeList 是节点列表类型,MouseEvent 是鼠标点击事件的类型……
let w:Window = window
// w.alert(1)
let ele:HTMLElement = document.createElement('div')
let allDiv:NodeList = document.querySelectorAll('div')
ele.addEventListener("click",function(e:MouseEvent){
const args:IArguments = arguments
w.alert(1)
console.log(args)
},false)
泛型
把所有变量和函数出现的地方都定义好类型,就可以在编译阶段提前规避出很多报错。然而 TypeScript 的能力可不止于此,TypeScript 可以进行类型编程,这会极大提高 TypeScript 在复杂场景下的应用场景。
function identity0(args:any):any{
return args
}
我们需要返回值的类型和参数一致,所以我们在函数名之后使用 <> 定一个泛型 T,你可以理解这个 T 的意思就是给函数参数定义了一个类型变量,会在后面使用,相当于【type T = arg 的类型】,返回值使用 T 这个类型就完成了这个需求。
function identity<T>(arg:T):T{
// console.log(arg)
return arg
}
identity<string>("vue")
identity<number>(111)
有了泛型之后,我们就有了把函数参数定义成类型的功能,我们就可以实现类似高阶函数的类型函数。
interface vueCourse5{
name:string,
price:number
}
keyof 可以帮助我们拆解已有类型
type courseProps = keyof vueCourse5
// let k:courseProps = true
let k1:courseProps = "name"
let k2:courseProps = "price"
使用 extends 来实现类型系统中的条件判断。
type ExtendsType<T> = T extends boolean ? string:number
let et:ExtendsType<string> = 123 //ExtendsType<string>===number
type ExtendsType1 = ExtendsType<string> // number
let et1:ExtendsType1 = 123
type ExtendsType2 = ExtendsType<true> // string
let et2:ExtendsType2 = "123"
extends 相当于 TypeScript 世界中的条件语句,然后 in 关键字可以理解为 TypeScript 世界中的遍历。
type courses = 'name'|'price'
type courseObj={
[k in courses]:number
}
let co:courseObj = {
'name':123,
'price':12333
}
function getProperty<T,K extends keyof T>(o:T,name:K):T[K]{
console.log(o[name])
return o[name]
}
const coursePrice:courseObj={
'name':1,
'price':2
}
getProperty(coursePrice,'price')
让我们拥有了给函数的参数定义类型变量的能力,infer 则是可以在 extends 之后的变量设置类型变量,更加细致地控制类型。
type Foo =()=>courseObj
type returnType<T>= T extends () =>infer P?P:string
type Foo1 = returnType<Foo>
type Foo2 = returnType<string>
let f:Foo1={
'name':1,
'price':2
}
let f2:Foo2="string"
实战练习
interface Todo{
title:string ,
desc:string,
done:boolean
}
type todo1 = keyof Todo
let td1:todo1 = "done"
type partTodo = Partial1<Todo>
我们需要实现类型函数 Partial1,返回的类型是 Todo 所有的属性都变成可选项。
type Partial1<T> = {
[K in keyof T]?:T[K]
}
//从两种type中筛选出不相同的类型
type Exclude1<T,K> = T extends K ?never:K
let ex:Exclude1<string,number> =111
let ex1:Exclude1<string,Todo>
type Pick1<T,K extends keyof T>={
[P in K]:T[P]
}
type pick2 = Pick1<partTodo,todo1>
例1:
sectionData: [
{
title: ["title1", "title2"],
content: [
{ icon: accountIcon, title: "account", path: "/account" },
{
icon: searchIcon,
title: "search",
path: "/search",
info: "search",
num: 0,
},
{
icon: record,
title: "record",
path: "/record",
info: "record",
},
],
},
]
ts 定义类型
class SectionDataType{
title:string[],
content:Array<contentType>=[]
}
interface contentType{
icon: string,
title: string,
path: string,
info?: string,
num?: number,
}