速度提升
¥Speed improvements
TypeScript 3.5 针对类型检查和增量构建引入了几项优化。
¥TypeScript 3.5 introduces several optimizations around type-checking and incremental builds.
类型检查加速
¥Type-checking speed-ups
TypeScript 3.5 在 TypeScript 3.4 的基础上进行了一些优化,以提高类型检查的效率。这些改进在编辑器场景中更加明显,因为在编辑器场景中,类型检查会驱动代码补全列表等操作。
¥TypeScript 3.5 contains certain optimizations over TypeScript 3.4 for type-checking more efficiently. These improvements are significantly more pronounced in editor scenarios where type-checking drives operations like code completion lists.
--incremental
改进
¥--incremental
improvements
TypeScript 3.5 改进了 3.4 的 incremental
构建模式,通过保存有关世界状态计算方式的信息。 - 编译器设置、查找文件的原因、文件的位置等。在涉及数百个使用 TypeScript 项目引用的 --build
模式项目的情况下,我们发现与 TypeScript 3.4 相比,重建时间最多可以减少 68%!
¥TypeScript 3.5 improves on 3.4’s incremental
build mode, by saving information about how the state of the world was calculated - compiler settings, why files were looked up, where files were found, etc.
In scenarios involving hundreds of projects using TypeScript’s project references in --build
mode, we’ve found that the amount of time rebuilding can be reduced by as much as 68% compared to TypeScript 3.4!
更多详情,请参阅拉取请求
¥For more details, you can see the pull requests to
Omit
辅助类型
¥The Omit
helper type
TypeScript 3.5 引入了新的 Omit
辅助类型,它会创建一个新类型,并删除原始类型的一些属性。
¥TypeScript 3.5 introduces the new Omit
helper type, which creates a new type with some properties dropped from the original.
ts
type Person = {name: string;age: number;location: string;};type QuantumPerson = Omit<Person, "location">;// equivalent totype QuantumPerson = {name: string;age: number;};
此处,我们能够使用 Omit
助手复制 Person
中除 location
之外的所有属性。
¥Here we were able to copy over all the properties of Person
except for location
using the Omit
helper.
更多详情,请参阅 查看 GitHub 上添加 Omit
的拉取请求 和 将 Omit
用于对象剩余操作的更改。
¥For more details, see the pull request on GitHub to add Omit
, as well as the change to use Omit
for object rest.
改进了联合类型中多余属性的检查
¥Improved excess property checks in union types
在 TypeScript 3.4 及更早版本中,某些不必要的属性是允许的。例如,TypeScript 3.4 允许在对象字面量中使用错误的 name
属性,即使其类型在 Point
和 Label
之间不匹配。
¥In TypeScript 3.4 and earlier, certain excess properties were allowed in situations where they really shouldn’t have been.
For instance, TypeScript 3.4 permitted the incorrect name
property in the object literal even though its types don’t match between Point
and Label
.
ts
type Point = {x: number;y: number;};type Label = {name: string;};const thing: Point | Label = {x: 0,y: 0,name: true // uh-oh!};
以前,非歧视联合不会对其成员进行任何额外的属性检查,因此,类型错误的 name
属性会被忽略。
¥Previously, a non-discriminated union wouldn’t have any excess property checking done on its members, and as a result, the incorrectly typed name
property slipped by.
在 TypeScript 3.5 中,类型检查器至少会验证所有提供的属性是否属于某个联合成员并具有适当的类型,这意味着上面的示例正确地触发了错误。
¥In TypeScript 3.5, the type-checker at least verifies that all the provided properties belong to some union member and have the appropriate type, meaning that the sample above correctly issues an error.
请注意,只要属性类型有效,仍然允许部分重叠。
¥Note that partial overlap is still permitted as long as the property types are valid.
ts
const pl: Point | Label = {x: 0,y: 0,name: "origin" // okay};
--allowUmdGlobalAccess
标志
¥The --allowUmdGlobalAccess
flag
在 TypeScript 3.5 中,你现在可以引用 UMD 全局声明,例如
¥In TypeScript 3.5, you can now reference UMD global declarations like
export as namespace foo;
来自任何地方 - 甚至模块 - 使用新的 allowUmdGlobalAccess
标志。
¥from anywhere - even modules - using the new allowUmdGlobalAccess
flag.
此模式为混合和匹配第三方库的方式增加了灵活性,库声明的全局变量始终可以被使用,即使在模块内部也可以。
¥This mode adds flexibility for mixing and matching the way 3rd party libraries, where globals that libraries declare can always be consumed, even from within modules.
详情请见 查看 GitHub 上的拉取请求。
¥For more details, see the pull request on GitHub.
更智能的联合类型检查
¥Smarter union type checking
在 TypeScript 3.4 及更早版本中,以下示例将失败:
¥In TypeScript 3.4 and prior, the following example would fail:
ts
type S = { done: boolean; value: number };type T = { done: false; value: number } | { done: true; value: number };declare let source: S;declare let target: T;target = source;
这是因为 S
不能分配给 { done: false, value: number }
或 { done: true, value: number }
。为什么?因为 S
中的 done
属性不够具体 - 它是 boolean
,而 T
的每个组成部分都有一个 done
属性,该属性具体是 true
或 false
。这就是我们所说的对每个组成类型进行单独检查的原因:TypeScript 不会简单地将每个属性合并在一起,然后检查 S
是否可以赋值给它。如果是这样,一些糟糕的代码可能会像下面这样通过:
¥That’s because S
isn’t assignable to { done: false, value: number }
nor { done: true, value: number }
.
Why?
Because the done
property in S
isn’t specific enough - it’s boolean
whereas each constituent of T
has a done
property that’s specifically true
or false
.
That’s what we meant by each constituent type being checked in isolation: TypeScript doesn’t just union each property together and see if S
is assignable to that.
If it did, some bad code could get through like the following:
ts
interface Foo {kind: "foo";value: string;}interface Bar {kind: "bar";value: number;}function doSomething(x: Foo | Bar) {if (x.kind === "foo") {x.value.toLowerCase();}}// uh-oh - luckily TypeScript errors here!doSomething({kind: "foo",value: 123});
但是,对于原始示例来说,这有点过于严格。如果你确定了 S
任何可能值的精确类型,你实际上可以看到它与 T
中的类型完全匹配。
¥However, this was a bit overly strict for the original example.
If you figure out the precise type of any possible value of S
, you can actually see that it matches the types in T
exactly.
在 TypeScript 3.5 中,当对具有判别属性的类型(例如 T
)进行赋值时,语言实际上会更进一步,将像 S
这样的类型分解为所有可能的居住类型的联合。在这种情况下,由于 boolean
是 true
和 false
的并集,因此 S
将被视为 { done: false, value: number }
和 { done: true, value: number }
的并集。
¥In TypeScript 3.5, when assigning to types with discriminant properties like in T
, the language actually will go further and decompose types like S
into a union of every possible inhabitant type.
In this case, since boolean
is a union of true
and false
, S
will be viewed as a union of { done: false, value: number }
and { done: true, value: number }
.
更多详情,请参阅 查看 GitHub 上的原始拉取请求。
¥For more details, you can see the original pull request on GitHub.
泛型构造函数的高阶类型推断
¥Higher order type inference from generic constructors
在 TypeScript 3.4 中,我们改进了泛型函数返回函数的推断,如下所示:
¥In TypeScript 3.4, we improved inference for when generic functions that return functions like so:
ts
function compose<T, U, V>(f: (x: T) => U, g: (y: U) => V): (x: T) => V {return x => g(f(x));}
将其他泛型函数作为参数,如下所示:
¥took other generic functions as arguments, like so:
ts
function arrayify<T>(x: T): T[] {return [x];}type Box<U> = { value: U };function boxify<U>(y: U): Box<U> {return { value: y };}let newFn = compose(arrayify, boxify);
与旧版本语言推断出的相对无用的类型 (x: {}) => Box<{}[]>
不同,TypeScript 3.4 的推断允许 newFn
具有泛型。它的新类型是 <T>(x: T) => Box<T[]>
。
¥Instead of a relatively useless type like (x: {}) => Box<{}[]>
, which older versions of the language would infer, TypeScript 3.4’s inference allows newFn
to be generic.
Its new type is <T>(x: T) => Box<T[]>
.
TypeScript 3.5 将此行为推广到构造函数。
¥TypeScript 3.5 generalizes this behavior to work on constructor functions as well.
ts
class Box<T> {kind: "box";value: T;constructor(value: T) {this.value = value;}}class Bag<U> {kind: "bag";value: U;constructor(value: U) {this.value = value;}}function composeCtor<T, U, V>(F: new (x: T) => U,G: new (y: U) => V): (x: T) => V {return x => new G(new F(x));}let f = composeCtor(Box, Bag); // has type '<T>(x: T) => Bag<Box<T>>'let a = f(1024); // has type 'Bag<Box<number>>'
除了上述组合模式之外,这种对泛型构造函数的新推断意味着在某些 UI 库(例如 React)中对类组件进行操作的函数可以更正确地对泛型类组件进行操作。
¥In addition to compositional patterns like the above, this new inference on generic constructors means that functions that operate on class components in certain UI libraries like React can more correctly operate on generic class components.
ts
type ComponentClass<P> = new (props: P) => Component<P>;declare class Component<P> {props: P;constructor(props: P);}declare function myHoc<P>(C: ComponentClass<P>): ComponentClass<P>;type NestedProps<T> = { foo: number; stuff: T };declare class GenericComponent<T> extends Component<NestedProps<T>> {}// type is 'new <T>(props: NestedProps<T>) => Component<NestedProps<T>>'const GenericComponent2 = myHoc(GenericComponent);
要了解更多信息,请参阅 查看 GitHub 上的原始拉取请求。
¥To learn more, check out the original pull request on GitHub.