TypeScript开发人员的5条诫命

图片


越来越多的项目和团队正在使用TypeScript。 但是,仅应用TypeScript并充分利用它是完全不同的事情。


我向您提供了使用TypeScript的高级最佳实践列表,它们将帮助您充分利用该语言。


不要撒谎


类型是合同。 这是什么意思? 当您实现一个函数时,其类型将成为对其他开发人员(或将来对您自己!)的承诺。调用该函数时,该函数将返回某种类型的值。


在下面的示例中, getUser函数的类型确保其返回始终具有两个属性的对象: nameage


 interface User { name: string; age: number; } function getUser(id: number): User { /* ... */ } 

TypeScript是一种非常灵活的语言。 它有许多折衷方案旨在促进语言的引入。 例如,它允许您像这样实现getUser函数:


 function getUser(id: number): User { return { age: 12 } as User; } 

不要那样做! 这是假的。 通过创建这样的代码,您可以与其他开发人员(他们将在其函数中使用您的函数)说谎。 他们希望getUser返回的对象将始终具有某种name字段。 但是他不在那里! 此外,当您的同事写getUser(1).name.toString()时会发生什么? 你很清楚...


当然,这里的谎言似乎很明显。 但是,在使用大型代码库的情况下,您常常会发现自己想要返回(或传递)的值几乎与预期类型匹配的情况。 找到类型不匹配的原因需要花费时间和精力,因此您很着急...因此您决定使用类型转换。


但是,这样做违反了神圣的合同 。 与使用类型转换相比,总是花些时间并理解为什么类型不匹配总比不上。 一些运行时错误很可能隐藏在表面之下。


不要撒谎。 遵守合同。


精确一点


类型是文档。 在记录功能时,您不想传达尽可能多的信息吗?


 //   function getUser(id) { /* ... */ } //     : name  age function getUser(id) { /* ... */ } //  id       id , //     : name  age. //     undefined. function getUser(id) { /* ... */ } 

您想要关于getUser函数的哪个注释? 您知道的函数返回越多,越好。 例如,知道它可以返回undefined ,您可以编写一个if块来检查在请求该对象的属性之前是否定义了该函数返回的对象。


类型完全相同:类型描述得越准确,它传达的信息就越多。


 function getUserType(id: number): string { /* ... */ } function getUserType(id: number): 'standard' | 'premium' | 'admin' { /* ... */ } 

getUserType函数的第二个版本提供了更多信息,因此调用者处在更为方便的情况下。 如果您可能知道(合同,还记得吗?)它将是给定的三行之一,而不仅仅是任何一行,则更容易处理该值。 首先要确定的是-值不能为空字符串。


让我们考虑一个更真实的例子。 State类型描述了从后端请求一些数据的组件的状态。 这种类型正确吗?


 interface State { isLoading: boolean; data?: string[]; errorMessage?: string; } 

使用此类型的客户端必须处理状态属性值的一些不太可能的组合。 例如,同时定义dataerrorMessage属性的情况是不可能的:数据请求可以成功也可以失败。


我们可以借助已区分的联合类型使类型更加准确:


 type State = | { status: 'loading' } | { status: 'successful', data: string[] } | { status: 'failed', errorMessage: string }; 

现在,使用此类型的客户端有了更多信息:他不再需要处理错误的属性组合。


精确点。 传递有关您类型的尽可能多的信息。


从类型开始


由于类型既是合同又是文档,因此它们对于设计功能(或方法)非常有用。


互联网上有许多文章建议程序员在编写代码前进行思考 。 我完全赞同这种方法。 直接跳转到代码的诱惑很大,但这常常导致错误的决定。 花一点时间思考实现总是可以带来丰厚的回报。


类型在此过程中非常有用。 通过思考可以创建与解决问题相关的功能类型的签名。 那很棒,因为您专注于函数的功能,而不用考虑它们的功能。


React JS具有高阶组件(HOC)的概念。 这些功能以某种方式扩展了给定的组件。 例如,您可以使用withLoadingIndicator创建一个高阶组件,该组件将加载指示器添加到现有组件。


让我们为此函数编写一个类型签名。 该函数接受组件输入并返回组件。 为了表示一个组件,我们可以使用React ComponentType类型。


ComponentType是一种通用类型,由组件属性的类型参数化。 withLoadingIndicator接受一个组件并返回一个新组件,该组件显示原始组件或加载指示器。 根据新逻辑属性isLoading的值来决定要显示什么。 因此,返回的组件需要与原始组件相同的属性,仅添加新的isLoading属性。


我们将确定类型。 withLoadingIndicator接受类型为ComponentType<P> ,其中P表示属性的类型。 withLoadingIndicator返回具有P & { isLoading: boolean }类型的高级属性的组件。


 const withLoadingIndicator = <P>(Component: ComponentType<P>) : ComponentType<P & { isLoading: boolean }> => ({ isLoading, ...props }) => { /* ... */ } 

在处理功能类型时,我们不得不考虑其输入将是什么,输出将是什么。 换句话说,我们必须设计一个函数 。 现在编写它的实现很容易。


从类型开始。 让类型迫使您先设计,然后再编写实现。


严谨


前三个诫命要求您特别注意类型。 幸运的是,解决此问题时,您不必自己做任何事情-通常TypeScript编译器会在类型说谎或类型不够准确时通知您。


通过包含--strict标志,可以帮助编译器更好地做到这一点。 这是一个--noImplicitAny所有严格类型检查选项的meta标志:-- --noImplicitAny ,-- --noImplicitThis ,-- --alwaysStrict ,-- --noImplicitAny ,-- --noImplicitThis ,-- --alwaysStrict--strictPropertyInitialization


这些标志做什么? 通常,将它们包含进来会导致TypeScript编译错误的数量增加。 这很好! 更多编译错误-编译器提供了更多帮助。


让我们看看打开--strictNullChecks标志如何帮助检测代码中的错误。


 function getUser(id: number): User { if (id >= 0) { return { name: 'John', age: 12 }; } else { return undefined; } } 

getUser类型可确保函数始终返回User类型的对象。 但是,请看一下实现:函数也可以返回undefined


幸运的是,启用--strictNullChecks标志会导致编译错误:


 Type 'undefined' is not assignable to type 'User'. 

TypeScript编译器检测错误。 要摆脱此错误,请诚实地说出全部事实:


 function getUser(id: number): User | undefined { /* ... */ } 

接受严格的类型检查。 让编译器保护您免受错误的侵害。


保持最新


TypeScript的发展速度非常快。 每两个月发布一个新版本。 每个版本都带来了重大的语言改进和新功能。


这种语言的新功能经常会导致您更准确地定义类型并更严格地检查它们。


例如,在版本2.0中引入了“区分联合类型”(我在“ 准确 ”命令中提到了它们)。


3.2版引入了编译器标志--strictBindCallApply ,该标志包括bindcallapply函数的正确类型。


3.4版改进了高阶函数中的类型推断 ,这使得在以函数样式编写代码时更容易使用精确类型。


我的立场是,了解TypeScript最新版本中引入的语言功能实际上是值得的。 通常,这可以帮助您遵循列表中的其他四个诫命。


正式的TypeScript路线图是一个很好的起点。 定期检查Microsoft Devblog中的TypeScript部分也将很不错,因为所有发行公告均已发布。


紧跟该语言的新功能,并为您服务。


总结


我希望该列表对您有所帮助。 一如既往,在所有事物中,不要盲目遵循这些诫命。 但是我坚信这些规则将使您成为更好的TypeScript开发人员。


我很高兴在评论中看到您对这个问题的想法。


红利


您喜欢这篇有关TypeScript的文章吗? 我确定您还会喜欢这个免费的PDF: 10个TypeScript开发错误,这些错误使您的代码不安全。

Source: https://habr.com/ru/post/zh-CN461565/


All Articles