大家好,我是ConardLi。TypeScript4.8于8月25日正式发布。这个版本带来了很多新特性。让我们来看看一些重要的变化:联合类型、交集类型和类型缩小优化。TypeScript4.8版本支持--strictNullChecks带来一系列准确性和一致性改进。主要体现在联合式、交叉式和收窄式的工作方式上。例如,unknown在本质上实际上接近联合类型{}|null|undefined,因为它可以接受null、undefined和任何其他类型。TypeScript现在可以识别这种情况并允许从未知类型赋值给{}|空|不明确的。函数f(x:未知,y:{}|null|undefined){x=y;//?y=x;//?}另一个变化是{}与任何其他对象类型的交集类型将缩减为此对象类型:{}&object;//object此外,不推荐使用{}&null和{}&undefined:{}&null;//从不{}&undefined;//never这样内置的NonNullable类型被简化成了下面的样子:?typeNonNullable=Textendsnull|不明确的?从不:T;?输入NonNullable=T&{};这些改进也增强了类型控制流分析的能力。例如,未知类型现在可以直接缩小为{}|空|undefined:functionnarrowUnknownUnion(x:{}|null|undefined){if(x){x;//{}}否则{x;//{}|空|未定义}}functionnarrowUnknown(x:unknown){if(x){x;//以前是'unknown',现在是'{}'}else{x;//unknown}}泛型值也会被相同类型缩小。比如我们检查一个值是null还是undefined的时候,就相当于让他和{}交叉,它和NonNullable是同一个类型。所以我们现在可以在不实现任何类型断言的情况下定义这样的函数:ConardLi:此处需要可空类型!”);}returnvalue;}优化inferinferinferintemplatestringinferinfer可以在extends的条件语句中推断出要推断的类型,比如下面的简单用法:typeReturnType=Textends(...args:any[])=>推断R?R:任何;在本例中,inferR表示要推断的返回值类型。如果T是一个函数,返回函数的返回值,否则返回any。让我们看一个更高级的类型推断示例:typeFirstIfString=Textends[inferS,...unknown[]]?S扩展字符串?S:never:never;//stringtypeA=FirstIfString<[string,number,number]>;//"hello"类型B=FirstIfString<["hello",number,number]>;//"hello"|“世界”类型C=FirstIfString<[“你好”|"world",boolean]>;//nevertypeD=FirstIfString<[boolean,number,string]>;FirstIfString是一个工具类型,意思是如果数据是数组,第一个元素是字符串类型,则返回第一个元素,否则从不返回。这种写法有点复杂,因为要判断第一个元素是不是字符串类型,所以需要额外写一个三元运算符,所以TypeScript4.7引入了更简洁的语法infer和extends可以一起使用:typeTryGetNumberIfFirst=Textends[inferUextendsnumber,...unknown[]]?你:从不;TypeScript4.8优化了模板字符串中inferextends的使用。在以下情况下,infer曾经被Constrainedtoaprimitivetype,现在可以推断出更精确的值://'number'->'100'.typeConardLiNum="100"extends`${inferUextendsnumber}`?U:never;//'bigint'->'100n'.typeConardLiBigInt="100"extends`${inferUextendsbigint}`?U:never;//'boolean'->'true'.typeConardLiBool="true"extends`${inferUextendsboolean}`?你:从不;对象类型比较错误提示在很多语言中,像==这样的运算符对对象进行所谓的“值”相等。例如,在Python中,通过使用==检查值是否等于空列表来检查列表是否为空:ifpeople_at_home==[]:print("here'swhereIlie,brokeninside.3")adopt_animals()但在JavaScript中不是这样。对象之间的==和===检查实际上是对两个对象的引用。这应该算是JavaScript早期的设计缺陷,所以TypeScript现在会针对以下代码提示错误:if(peopleAtHome===[]){//~~~~~~~~~~~~~~~~~~//此条件将始终返回“false”,因为JavaScript通过引用而不是值来比较对象。console.log("here'swhereIlie,brokeninside.3")adoptAnimals();}禁止在JavaScript文件中导入/导出类型TypeScript以前允许JavaScript文件在导入和导出语句中导入和导出带有类型的声明,但是不支持值的导入导出。这种行为是不正确的,因为不存在的值的命名导入和导出可能会导致ECMAScript模块下的运行时错误。当在--checkJs下或通过//@ts-check注释检查JavaScript文件类型时,TypeScript现在会抛出错误。//@ts-checkimport{someValue,SomeType}from"some-module";/***@type{SomeType}*/exportconstmyValue=someValue;/***@typedef{string|number}MyType*///将在运行时失败,因为“MyType”不是value.export{MyTypeasMyExportedType};要从另一个模块引用一个类型,你可以直接限定导入:/**?*@type{SomeType}?*@type{import("some-module").SomeType}*/exportconstmyValue=someValue;要导出类型,只需在JSDoc中使用/**@typedef*/注释。@typedef注释已经自动从它们包含的模块中导出类型。/***@typedef{字符串|number}MyType*/?/**?*@typedef{MyType}MyExportedType?*/?export{MyTypeasMyExportedType};--build,--watch,--incremental性能优化TypeScript4.8引入了多项优化来提高--watch和--incremental和--build的性能。例如,TypeScript现在可以处于--watch模式,以避免非用户更改引起的额外更改,避免与可能监视TypeScript输出的其他构建工具发生冲突,增量重用,以及其他改进。实验表明,对于大型内部代码库上的许多简单常见操作,时间减少了10%-25%,在没有文件更改的情况下,时间减少了大约40%。以下是TypeScript代码库的测试: