1、使用typeof守卫进行类型缩小
报错是因为JavaScript历史遗留问题 ,null也是object类型,如果是null就不能遍历
2、使用真值进行类型缩小
通过布尔否定叹号把逻辑从否定分支中过滤掉
function printAll(strs:string|string[]|null){
// strs && 真值的自动类型转换 说明是一个有效的字符串
if(strs && typeof strs === 'object'){
for(const s of strs){
}
}else if(typeof strs === 'string'){
console.log(strs);
}else{
//...
}
}
function multiplyAll(
values:number[]|undefined,
factor:number
){
if(!values){
return values
}else{
return values.map((x)=>{
return x*factor
})
}
}
console.log(multiplyAll([3,4],2));
3、等值缩小
function example(x: string | number, y: string | boolean) {
if (x === y) {
x.toUpperCase()
y.toLowerCase()
}else{
console.log(x);
console.log(y);
}
}
function printAll1(strs:string|string[]|null){
if(strs!==null){
if(typeof strs === 'object'){
for(const s of strs){
}
}else if(typeof strs === 'string'){
console.log(strs);
}else{
//...
}
}
}
interface Container{
value:number|null|undefined
}
function multiplyValue(container:Container,factor:number){
if(container.value!=null){
console.log(container.value);
container.value*=factor
}
}
multiplyValue({value:5},6)
multiplyValue({value:undefined},6)
multiplyValue({value:null},6)
4、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){
// return animal.swim()//报错 原因是animal有可能是Fish或者Human
// 解决方法 加类型断言
return (animal as Fish).swim()
}
// return animal.fly()//报错 原因是animal有可能是Bird或者Human
// 解决方法 加类型断言
return (animal as Bird).fly()
}
5、instanceof操作符缩小
function logValue(x:Date|string){
// 检查一个值是否是另外一个值的实例
if(x instanceof Date){
// 检查x的原型链是否含有Date.prototype
console.log(x.toUTCString());
}else{
console.log(x.toUpperCase());
}
}
logValue(new Date)
logValue('hello ts')
6、分配缩小
7、控制流分析
function example1(){
let x : string | number | boolean
x = Math.random() < 0.5
// x:boolean
console.log(x);
if(Math.random()<0.5){
x = 'hello'
// x:string
console.log(x);
}else{
x = 100
// x:number
console.log(x);
}
return x
}
let x1 = example1()
x1 = 'hello'
x1 = 100
// x1 = false //报错 不能将类型“boolean”分配给类型“string | number”。
8、类型谓词
type Fish2 = {
name:string,
swim:()=>void
}
type Bird2 = {
name:string,
fly:()=>void
}
function isFish2(pet:Fish2|Bird2):pet is Fish2{
return (pet as Fish2).swim !== undefined
}
function getSmallPet():Fish2|Bird2{
let fish:Fish2 = {
name:'sharkey',
swim:()=>{
}
}
let bird:Bird2 = {
name:'sparrow',
fly:()=>{
}
}
return true ? bird :fish
}
let pet = getSmallPet()
if(isFish2(pet)){
pet.swim()
}else{
pet.fly()
}
const zoo:(Fish2|Bird2)[] = [getSmallPet(),getSmallPet(),getSmallPet()]
const underWater1:Fish2[] = zoo.filter(isFish2)
const underWater2:Fish2[] = zoo.filter(isFish2) as Fish2[]
const underWater3:Fish2[] = zoo.filter((pet):pet is Fish2 => {
if(pet.name === 'frog'){
return false
}
return isFish2(pet)
})
9、受歧视的union
// interface Shape {
// kind:'circle'|'square',
// radius?:number,
// sideLength?:number
// }
interface Circle {
kind:'circle',
radius:number
}
interface Square {
kind:'square',
sideLength:number
}
type Shape = Circle | Square
// function getArea(shape:Shape){
// if(shape.kind==='circle'){
// return Math.PI * shape.radius ** 2
// }
// }
function getArea(shape:Shape){
switch(shape.kind){
case 'circle':
return Math.PI * shape.radius ** 2
break
case 'square':
return shape.sideLength**2
break
}
}
10、never类型与穷尽性检查
interface Circle {
kind:'circle',
radius:number
}
interface Square {
kind:'square',
sideLength:number
}
interface Triangle {
kind:'triangle',
sideLength:number
}
type Shape = Circle | Square | Triangle
function getArea(shape:Shape){
switch(shape.kind){
case 'circle':
return Math.PI * shape.radius ** 2
break
case 'square':
return shape.sideLength**2
break
default:
// never帮助做穷尽的检查
// const _exhaustiveCheck:never = shape//不能将类型“Triangle”分配给类型“never”。
// return _exhaustiveCheck
}
}