无比打字与拼英打字_打字稿4 0我最兴奋的是什么

无比打字与拼英打字

On August 20th, the team behind TypeScript officially released its 4.0 version. This is the most advanced version of the language, interpreter, and even their website to this date.

8月20日,TypeScript背后的团队正式发布了其4.0版本。 这是迄今为止该语言,解释器甚至其网站的最高级版本。

And with the announcement came the list of updates, which surprisingly for a major version change, they weren’t that many. Don’t get me wrong, they’re major changes that required a lot of design work and a lot of coding hours by a lot of people. And in this article I’m going to cover the major ones, if you want to read the official release with everything that changed, you can click here.

随着公告的发布,更新列表令人惊讶,对于主要的版本更改而言,更新的数量并不多。 不要误会我的意思,它们是重大更改,需要很多人进行大量的设计工作和大量的编码时间。 在本文中,我将介绍主要内容,如果您想阅读所有已更改内容的正式发行版,请单击此处

So without further ado, let’s get to the list of the changes I’m most excited about, shall we?

因此,事不宜迟,让我们进入我最兴奋的更改列表,对吧?

构造函数的类属性推断 (Class Property Inference from Constructors)

Number one of the list is this little puppy. Every time the language (or the interpreter) works in your favor in order to save you time and keystrokes, I’m up for it. In this case, TypeScript is now performing control flow analysis to understand what kind of values you’re assigning to your class’ properties. If the analysis is able to determine that there are no unreachable paths, then it’ll be able to assume their types.

名单上的第一名是这只小狗。 每当您使用该语言(或翻译)以节省您的时间和按键时,我都会支持。 在这种情况下,TypeScript现在将执行控制流分析,以了解您要为类的属性分配什么样的值。 如果分析能够确定没有不可达的路径,那么它将能够假定其类型。

Let me explain with a quick example:

让我用一个简单的例子来解释:

//Clear paths, so this works and assumes "string" for all properties
class Person {
  full_name;
  first_name;
  last_name;
  
  contructor(full_name: string) {
    this.full_name = full_name;
    this.first_name = full_name.split(" ")[0]
    this.last_name = full_name.split(" ")[1]
  }
}


//This doesn't work since not all paths are clear
class Person {
  full_name;
  first_name;
  last_name;
  
  contructor(full_name: string) {
    this.full_name = full_name;
    if(Math.random()) {
      this.first_name = full_name.split(" ")[0]
      this.last_name = full_name.split(" ")[1]
    }
  }
}

The second version of the class has one code path (the IF statement) that is not always going to be used, which means that first_name and last_name won’t always have a value assigned with this code. And because of that TS’s interpreter won’t be able to infer the type for them. The first example though, with clear code paths, is a perfect sample of how you can avoid having to define the types and let the interpreter infer them from your logic.

该类的第二个版本具有一个并非总是要使用的代码路径(IF语句),这意味着first_namelast_name不会总是为此代码分配一个值。 因此,TS的解释器将无法为他们推断类型。 但是,第一个示例具有清晰的代码路径,它是如何避免必须定义类型并让解释程序从逻辑中推断出它们的完美示例。

Tip: Share your reusable components between projects using Bit (Github). Bit makes it simple to share, document, and organize independent components from any project.

提示:使用Bit ( Github )在项目之间共享可重用组件 。 Bit使共享,记录和组织来自任何项目的独立组件变得简单

Use it to maximize code reuse, collaborate on independent components, and build apps that scale.

使用它可以最大程度地重复使用代码,在独立组件上进行协作以及构建可扩展的应用程序。

Bit supports Node, TypeScript, React, Vue, Angular, and more.

Bit支持Node,TypeScript,React,Vue,Angular等。

Image for post
Example: exploring reusable React components shared on Bit.dev
示例:探索在 Bit.dev上共享的可重用React组件

标记的元组元素 (Labeled Tuple Elements)

This is a relatively smaller update compared to the previous one but you can now label elements inside your tuples.

与前一个相比,这是一个相对较小的更新,但是您现在可以在元组中标记元素。

Essentially, what this change was addressing was the fact that if you define a function with a rest parameter, when reading that function’s signature or even when reading the IDE’s tooltip for that function, the actual intent for it is not entirely clear. Look at the following image:

本质上,此更改要解决的事实是,如果您使用rest参数定义一个函数,则在读取该函数的签名时,甚至在读取该函数的IDE工具提示时,其实际意图还不是很清楚。 看下图:

Image for post

The tooltip states params_0 and params_1 , in this case, for such a simple function this wouldn't matter, but you can see how, for a more complex function, not having names for these parameters can harm readability. So with TypeScript 4.0, you can now add the labels and you’d have an improved tooltip like this:

在这种情况下,工具提示会说明params_0params_1无关紧要,但您可以看到,对于更复杂的功能,没有这些参数的名称会如何损害可读性。 因此,使用TypeScript 4.0,您现在可以添加标签,并且可以得到如下改进的工具提示:

Image for post

But wait a second, this is not the only use for these labels. Thanks to them, you can now create type-level overloads like this without any issues:

但是请稍等,这并不是这些标签的唯一用途。 多亏了他们,您现在可以像这样创建类型级别的重载而没有任何问题:

Image for post

The tooltip will show all three overloads, and thanks to the labels, they will make a lot more sense than something that says param_0: string, param_1: number .

工具提示将显示所有三个重载,并且param_0: string, param_1: number标签,它们将比说param_0: string, param_1: number东西有意义得多。

A few considerations about labeled tuples:

关于标记元组的一些注意事项:

  1. If you use labels for one item in the tuple, you have to use them for all elements.

    如果对元组中的一项使用标签,则必须对所有元素使用它们。
  2. You can also define optional elements in the tuple, by taking advantage of the label by adding a ? at the end of it:

    您还可以通过添加标签来利用标签来在元组中定义可选元素? 最后:

type Person = [name: string, address?: string]

可变参数元组类型 (Variadic Tuple Types)

This one has a very interesting name, doesn’t it? It took me a while to understand it, but let’s go step by step.

这个名字很有趣,不是吗? 我花了一些时间来理解它,但让我们一步一步地走。

We’ve already covered the concept of tuples, but just to be sure, a tuple is essentially a list with a pre-set length and where the type of every element is known. So the following are valid tuples:

我们已经介绍了元组的概念,但是可以肯定的是,元组本质上是一个具有预设长度的列表,并且每个元素的类型都在其中。 因此,以下是有效的元组:

type PersonParams = [name: string, age: number]let me:PersonParams = ['Fernando Doglio', 36]

Tuples, as we’ve seen above, now can have named elements as well, but the point about them, is that they have this pre-set structure, which we can use to define the rest parameter of a function (again, already somewhat covered above, but let me elaborate):

正如我们上面所看到的,元组现在也可以具有命名元素,但是关于它们的要点是它们具有这种预设结构,我们可以使用它来定义函数的其余参数(再次,已经有些以上已涵盖,但让我详细说明):

type PersonParams = [name: string, age: number]


function createPerson(...params: PersonParams): void {
  //... logic goes here
}


function createPerson(city: string, postalCode: string, ...otherParameters: PersonParams): void {
  ///.... logic goes here
}

Notice how the rest parameter always needs to be the last one. We’re limited by that, because of how JavaScript has defined this property. However, variadic tuples allow for a more flexible definition by letting us put the rest parameter wherever we want.

请注意,rest参数始终总是最后一个。 由于JavaScript定义此属性的方式,我们受到了限制。 但是, 可变参数元组允许我们将rest参数放置在所需的位置,从而使定义更加灵活。

In fact, with variadic tuples, we can also define generic types, which essentially let us create semi-defined tuples, where we can leave room for flexibility, let me explain:

实际上,对于可变参量元组,我们还可以定义泛型类型,从本质上讲,我们可以创建半定义的元组,在其中我们可以留出灵活性的空间,请允许我解释一下:

type FlexibleType<T extends unknown[]> = [string, ...T, string]


type AllStrings = FlexibleType<[string]> //this allows for [string, string, string]
type StringAndNumber = FlexibleType<[number]> //... [string, number, string]
type StringAndBools = FlexibleType<[bool, bool]> ///....[string, bool, bool, string]

So, as you can see, with variadic tuples, we can define a basic structure for our types and then extend them in order to add whatever extra we need into it.

因此,如您所见,对于可变参量元组,我们可以为我们的类型定义一个基本结构,然后对其进行扩展,以便在其中添加所需的任何其他内容。

That’s cool and all, but what can we actually do with this? Well if you apply this flexibility to function property definition, you can define patterns. For example, having a callback as the last parameter, is a very common pattern in Node.js with asynchronous functions. You can define something like that with variadic tuples in TypeScript:

太酷了,但实际上我们该怎么办? 如果将这种灵活性应用于函数属性定义,则可以定义模式。 例如,在最后一个具有异步功能的Node.js中,将回调作为最后一个参数是一种非常常见的模式。 您可以在TypeScript中使用可变参数元组定义类似的内容:

/// Generic variadic tuples
type CallbackFn<T extends unknown[]> = (Error, [...T]) => any;


type AsyncFn<T extends unknown[]> = (...arguments: [...T, CallbackFn<T>]) => any;


//Using the tuples


/**
 *  readFile('filename.txt', (err: Error, content: string) => {
     //.... my logic
 *  })
 */
const readFile: AsyncFn<[string]> = (filename: string, 
                                     cb: CallbackFn<[string]>) => { }; 


class DbRecord {


}


/**
 * dbQuery('select ? from ? where id = ?', ['*', 'tablename', 123], (err: Error,  results: DbRecord[]) => {
     ///.... my logic here
 * })
 */
const dbQuery: AsyncFn<[string,any[]]> = (queryString: string, 
                                          values: any[], 
                                          cb: CallbackFn<[DbRecord[]]>) => void {
    
}

As you can see, I actually defined two tuples here at the top of the code, one for callback functions, since there is also a very well known pattern where the first argument is the error and the second (and potentially others) contain the data of the “happy path” (where there are no errors). The second tuple makes use of the pattern and creates a new one where the callback function is the last element in an undetermined list of parameters.

如您所见,我实际上在代码顶部定义了两个元组,一个用于回调函数,因为还有一个众所周知的模式,其中第一个参数是错误 ,第二个(可能还有其他)包含数据的“幸福之路”(没有错误)。 第二个元组利用该模式并创建一个新的元组,其中回调函数是未确定的参数列表中的最后一个元素。

Finally we’re using these tuple definitions to define our own functions, and you can see how easy it is to use these generic templates of functions to define our own custom ones, that follow the same pattern.

最后,我们使用这些元组定义来定义我们自己的函数,并且您可以看到使用这些通用的函数模板来定义遵循相同模式的自定义模板是多么容易。

So, in the end, variadic tuples are here to simpify the way we can define a generic tuple, which we can then use anywhere (including on function definitions) to create specific versions of it following the same pattern.

因此,最后, 可变参数元组将简化我们定义通用元组的方式,然后我们可以在任何地方(包括函数定义)使用它来按照相同的模式创建其特定版本。

编辑器的一些改进 (Some Editor Improvements)

Other than the above changes (and other minor ones I’m not mentioning here), version 4.0 brought some editor-specific changes to the table, such as:

除了上述更改(以及我在此未提及的其他次要更改)之外,4.0版还对表进行了一些特定于编辑器的更改,例如:

转换为可选链接 (Convert to Optional Chaining)

In case you don’t know what optional chaining is, is a new feature from JavaScript, which allows you to write chain your property access code (or your chained method calls) in a way that if one of them doesn’t exists (or returns null or undefined, thus cutting the chain short) the code won’t throw a nasty exception (you can read more about it here).

如果您不知道什么是可选链接,这是JavaScript的一项新功能,它允许您编写属性访问代码(或链接的方法调用)的链接,以确保它们中的任何一个都不存在(或返回null或undefined,从而缩短了代码链)代码不会引发讨厌的异常(您可以在此处了解更多信息 )。

Before this feature, you would have to make sure every step prior to the final link on the chain existed before actually accessing it, something like:

使用此功能之前,您必须确保在实际访问链之前,链上最终链接之前的每个步骤都存在,例如:

obj.a && obj.a.b && obj.a.b.c && obj.a.b.c.d()

Now, you can select that code and click on “Convert to Optional Chain expression” and the editor will refactor that code for you.

现在,您可以选择该代码,然后单击“转换为可选链表达式”,编辑器将为您重构该代码。

Image for post
Image for post

Note that this was tested on Visual Studio Code using TypeScript 4, I don’t know how other editors might handle this change.

请注意,这已使用TypeScript 4在Visual Studio Code上进行了测试,我不知道其他编辑器可能如何处理此更改。

/** @deprecated */支持 (/** @deprecated */ Support)

This allows you to add that comment on top of the methods or functions you’re trying to deprecate and the editor will issue a related warning when suggesting auto-completition options:

这使您可以在尝试弃用的方法或函数的顶部添加该注释,并且编辑器在建议自动完成选项时将发出相关警告:

Image for post

Notice the name of the function, that means you should not be using it anymore.

注意函数的名称,这意味着您不再应该使用它。

Again, this test was done using VS Code, other editors might change the way they handle this notification.

同样,此测试是使用VS Code完成的,其他编辑者可能会更改其处理此通知的方式。

重大变化 (Breaking changes)

Finally, before closing this article I’d like to quickly go over the breaking changes from this version, because they’re the ones that might affect you the most.

最后,在结束本文之前,我想快速浏览一下此版本中的重大更改,因为它们是对您影响最大的更改。

DOM类型定义更改 (DOM type definition changes)

Their lib.d.ts definition changes removing the document.origin object. This was done because it only worked with older versions of IE and Safari. You should instead use self.origin for the same result.

他们的lib.d.ts定义更改,删除了document.origin对象。 这样做是因为它仅适用于IE和Safari的旧版本。 您应该改为使用self.origin获得相同的结果。

用属性覆盖属性访问器 (Overriding property accessors with properties)

This uses to be an error only if you used the useDefineForClassField option, but now overriding your property accessors with a property ( and the opposite as well) is always going to be an error:

仅在使用useDefineForClassField选项时, useDefineForClassField是错误,但是现在用属性(以及相反的属性)覆盖属性访问器总是会出错:

class BaseClass {
    get foo() {
        return 100;
    }
    set foo() {
        // ...
    }
}


class Derived extends BaseClass {
    foo = 10; //WRONG!: foo is an accessor, you can't override it here
}


///


class BaseClass {
    prop = 10;
}


class Derived extends BaseClass {
    get prop() { //WRONG!: foo is a property already, you can't override it here
       return 100;
    }
}

仅删除可选属性 (Deleting only optional properties)

Now, anything you want to delete with the delete operator has to be optional (actually, either optional, or of types any, unknown or never ). Which makes sense if you think about it, because if you’re planning on deleting something, that something needs to specify somehow that it might be undefined at one point of the execution of your code, otherwise you might start seeing unpredictable behavior, which is exactly the opposite of what we’re trying to achieve by using TypeScript in the first place.

现在,要使用delete运算符删除的任何内容都必须是可选的(实际上是可选的,或者类型为anyunknownnever )。 如果您考虑一下,这是有道理的,因为如果您打算删除某些内容,那么某些内容需要以某种方式指定在代码执行的某个时刻可能undefined该内容,否则您可能会开始看到不可预测的行为,即与我们最初尝试使用TypeScript实现的目的恰好相反。

结论 (Conclusion)

There are a few minor things I’ve left out, mainly because they don’t add A LOT to the table, but then again, if you want to see the full list of changes, check out their official statement.

我遗漏了一些小事情,主要是因为它们没有在表中添加很多,但是再次,如果您想查看更改的完整列表,请查看其正式声明

What do you think about the new features from TypeScript 4? Are you excited to start using it? I know I am! Which one is your favorite? Mine is definitely the variadic tuples, I love being able to define generic patterns that can then be applied and specialized everywhere!

您如何看待TypeScript 4的新功能? 您为开始使用它感到兴奋吗? 我知道我是! 哪一个是你的最爱? 我的绝对是可变参数元组,我喜欢能够定义通用模式,然后将其应用到任何地方并使其专业化!

Leave a comment down below with your favorite ones and let’s discuss!

在下面留下您最喜欢的评论,让我们讨论!

学到更多 (Learn More)

翻译自: https://blog.bitsrc.io/typescript-4-0-what-im-most-excited-about-4ee89693e02e

无比打字与拼英打字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值