TypeScript中as关键字的机制解析及常见疑问解答
关于TypeScript
as类型断言的表现疑问 先看示例代码:
type Fish = { swim: () => void }; type Bird = { fly: () => void }; function getSmallPet(): Fish | Bird { let bird: Bird = {fly: () => { console.log("airrrr") }} let fish: Fish = {swim: () => { console.log("whoosh") }} return Math.random() > 0.5 ? fish : bird } let pet = getSmallPet(); let fishPet = pet as Fish; // 若pet实际是fish,应该返回带swim方法的对象? let birdPet = pet as Bird; // 若pet实际是bird,应该返回带fly方法的对象? console.log("fish is") console.log(fishPet) console.log("bird is") console.log(birdPet) // 为何上述两个对象都显示为空? if (fishPet.swim) { fishPet.swim(); } else if (birdPet.fly) { birdPet.fly(); } // 但我们仍能成功调用其中一个方法,输出"airrr"或"whoosh",这是为什么?
问题解析:
console.log显示空对象的原因:
控制台打印对象时,默认不会展示函数类型的属性(除非手动展开对象查看)。你的Fish和Bird对象仅包含方法属性,所以控制台直接输出{},但这些方法属性在运行时是真实存在的。as类型断言的本质:as是TypeScript的类型断言,完全不影响运行时的代码,它只是给TypeScript编译器一个提示:“我确认这个变量是我断言的类型,不用再做类型检查了”。它不会修改原对象的结构或内容,不管你断言成什么类型,运行时的对象还是getSmallPet()返回的原始对象。
比如如果pet实际是Bird类型,pet as Fish不会把它转换成Fish对象,只是让TS编译器把它当作Fish处理,运行时它依然是带有fly方法的Bird对象。方法能成功调用的原因:
运行时的fishPet和birdPet其实都是同一个原始对象的引用。如果返回的是Bird,那birdPet就是原Bird对象,fly方法存在;fishPet虽然被断言成Fish,但运行时它还是Bird对象,没有swim方法,所以代码会进入else分支调用birdPet.fly()。反之返回Fish时,fishPet的swim方法存在,能正常执行。
内容的提问来源于stack exchange,提问作者Issac Howard
相关产品推荐
相关产品推荐

