这是我参与「第五届青训营 」伴学笔记创作活动的第4天。
JS没有表达不同代码单元之间关系的能力。编程最常见的是类型错误。TS的目标是成为JS程序的静态类型检查器,是JS的超集,添加了可选的对象类型。TS可以检查非异常故障。静态类型检查设置的越严格,越需要编译更多的代码,但从长远来看是值得的。可读性增强,可维护性增强。
动态语言和静态语言的差异主要是:编译发生在执行前还是执行时。
优化编译
- tsc --init #生成配置文件:解决ts和js中函数名重复的problems
- tsc --watch 自动编译:将修改后的TS直接编译成JS
- tsc -noEmitOnError hello.ts 表示在TS出现错误时并不进行编译成JS
数据类型
变量上会写类型注释,没有写时TS会推测一个变量的类型。
let myName: string = 'Felixlu' //myName是字符串,不能将别的类型赋值给它。即便不写: string,TS也会推断出myName类型
三个基元类型:string、number、Boolean
let str:string="hello typescript"
let num:number=100;
let bool:boolean=true
数组类型
let arr:number[]=[1,2,3]
let arr2:Array<number>=[1,2,3]
arr2=[4]
any:不希望某个特定值导致类型检查错误。当一个值的类型是any时可以访问它的任何属性,将它赋值给任何值。
let obj:any={
x:0
}
//any不会进行任何检查,以下的代码都不会报错,编译成js后运行的话会报错。
obj.foo()
obj()
obj.bar=100
obj='hello'
const n:number=obj
bigint:非常大的整数 symbol:全局唯一引用
匿名函数,当一个函数出现在TS可以确定它会被如何调用的地方的时候,这个函数的参数会自动指定类型。
定义函数形参的对象的类型:
function printCoord(pt:{x:number;y:number}){
console.log('坐标的x值为'+pt.x)
console.log('坐标的y值为'+pt.y)
}
printCoord({
x:3,y:7
})
联合类型union
let id:number|string //表示id可以是number或string中的一种
function welcome(x:string[]|string){ //表示x可以是字符串,也可以是数组中包字符串
if(Array.isArray(x)){
console.log('hello'+x.join('and')) //如果要用类型不同的方法,需要写if区分传入的类型再进行处理
}else{
console.log('welcome lone traveler'+x)
}
}
welcome('A') //可以传入字符串
welcome(['a','b','c']) //可以传入数组中放字符串
//number[]是数值数组,string[]是字符串数组
类型别名
type Point = {
x:number;
y:number
}
function print(pt:Point){
...
}
print({
x:100,
y:200
})
接口
interface ITF{
x:number
y:number
}
function print2(pt:ITF){
}
print({
x:100,
y:200
})
类型别名和接口之间的不同:几乎所有可以使用interface定义的类型都可以使用type定义,但接口可以拓展。
通过interface向现有的类型添加字段。但不能往type定义的类型中添加字段,只能通过&符号拓展。
类型断言
//两种类型断言的语法
const myCanvas=document.getElementById('main_canvas') as HTMLCanvasElement
const myCanvas2=<HTMLCanvasElement>document.getElementById('main_canvas')
文字类型
function printText(s:string,alignment:'left'|'right'|'center'){
...
}
printText('hello','left')
//数字类型
function compare(a:string,b:string): -1 | 0 | 1{
return a===b? 0:a<b?1:-1
}
interface Options{
width:number
}
function configure(x:Options|'auto'){
...
}
configure({
width:100
})
configure('auto')
//布尔类型 必须是对应的布尔值
let b1:true=true
let b2:false=false
null和undefined
let x:undefined=undefined
let y:null=null
function liveDangerously(x?:number | null){
console.log(x!.toFixed())
} //上面感叹号表示你明确知道x不可能是null或undefined类型。问号?表示可以没有x这个参数
枚举
//枚举
enum Direction{
Up=5,
Down,
Left,
Right
}
console.log(Direction.Up) //5
console.log(Direction.Down) //6
类型缩小
宽类型=>窄类型。将特殊的检查称为类型防护。将类型用typeof细化为比类型声明更具体的范围的行为称为类型缩小。
typeof类型守卫
typeof strs === "object" |"string" | "number" | "bigint" |"boolean" | "symbol" |"undefined" |"function"
//typeof null === "object"
真值缩小
function printAll(strs:string|string[]|null){
////strs&& 用于确保strs不是null
if(strs && typeof strs ==="object"){
for(const s of strs){
console.log(s);
}
}else if(typeof strs==="string"){
console.log(strs);
}else{
//...
}
}
等值缩小
function multiplyValue(container:Container,factor:number){
if(container.value!=null){
console.log(container.value)
container.value*=factor
}
}
multiplyValue({value:5},6) //30
multiplyValue({value:undefined},6) //不输出 被过滤掉了
in操作符缩小
type Fish={swim:()=>void}
type Bird={fly:()=>void}
type Human={ swim?:()=>void;fly?:()=>void}
function move(animal:Fish|Bird|Human){
if("swim" in animal){//这里写in来筛选一些属性
return (animal as Fish).swim()//这里写as来确定类型,类型断言
}
return (animal as Bird).fly()
}
instanceof操作符缩小
function logValue(x:Date | string){
if(x instanceof Date){
console.log(x.toUTCString())
//toUTCString() 方法根据世界时将 Date 对象转换为字符串。
}else{
console.log(x.toUpperCase())
}
}
logValue(new Date())
logValue('hello ts')
分配缩小
//let x:string|number
let x=Math.random()<0.5?10:'hello world'
//let x:number
x=1
console.log(x)
//let x=string
x='goodbye'
console.log(x)
受歧视的unions
interface Circle{
kind:'circle'
radius:number
}
interface Square{
kind:'square'
sideLength:number
}
type Shape=Circle|Square
//用switch来选则不同的类型
function getArea(shape:Shape){
//因为radius属性是可选择的,可能没有,所以我们在radius后面加一个!,告诉ts这个属性是一定存在的。
// return Math.PI*shape.radius!**2
switch(shape.kind){
case 'circle':
return Math.PI*shape.radius**2
case 'square':
return shape.sideLength**2
}
}
never
never进行穷尽性检查。