TypeScript と JavaScript は、近年着実に発展しています。私たちはこれまでコードを書くときにいくつかの習慣を身につけてきましたが、その中にはあまり意味のないものもあります。私たちがやめるべき10の悪い習慣を紹介します。
strict
モードを使用しない書かれていません厳密モード tsconfig.json
。
{ "compilerOptions": { "target": "ES2015", "module": "commonjs" } }
strict
モードを有効にするだけです:
{ "compilerOptions": { "target": "ES2015", "module": "commonjs", "strict": true } }
既存のコード ベースにより厳格なルールを導入するには時間がかかります。
ルールを厳格化すると、将来のコードの保守が容易になり、時間を大幅に節約できます。
||
|| フォールバック処理のデフォルト値を使用します:
function createBlogPost (text: string, author: string, date?: Date) { return { text: text, author: author, date: date || new Date() } }
を使用しますか?? 演算子を使用するか、パラメータのデフォルト値を再定義します。
function createBlogPost (text: string, author: string, date: Date = new Date()) return { text: text, author: author, date: date } }
?? 演算子は、長い関数で値を使用するときに昨年導入されたばかりです。これをパラメータのデフォルトとして設定するのは難しい場合があります。
?? は
||、
?? とは異なります。
null または
unknown にのみ適用され、すべての仮想値には適用されません。
async function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') const products: any = await response.json() return products }
どうすればいいですかunknown
async function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') const products: unknown = await response.json() return products as Product[] }
これが悪い習慣である理由any がよく使用されます。たとえば、TypeScript チームは、上記の例の
response.json() の型を
Promise に設定します。
これを実行してはいけない理由
4.
この習慣はどのようなものですかasync function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') const products: unknown = await response.json() return products as Product[] }
どうあるべきか
function isArrayOfProducts (obj: unknown): obj is Product[] { return Array.isArray(obj) && obj.every(isProduct) } function isProduct (obj: unknown): obj is Product { return obj != null && typeof (obj as Product).id === 'string' } async function loadProducts(): Promise<Product[]> { const response = await fetch('https://api.mysite.com/products') const products: unknown = await response.json() if (!isArrayOfProducts(products)) { throw new TypeError('Received malformed products API response') } return products }
なぜこれが悪い習慣なのでしょうか?as SomeOtherType を使用して変換を高速化できます。
これを実行してはいけない理由
5.
この習慣はどのようなものですかinterface User { id: string firstName: string lastName: string email: string } test('createEmailText returns text that greats the user by first name', () => { const user: User = { firstName: 'John' } as any expect(createEmailText(user)).toContain(user.firstName) }
何をすべきか
interface User { id: string firstName: string lastName: string email: string } class MockUser implements User { id = 'id' firstName = 'John' lastName = 'Doe' email = 'john@doe.com' } test('createEmailText returns text that greats the user by first name', () => { const user = new MockUser() expect(createEmailText(user)).toContain(user.firstName) }
なぜこれが悪い習慣なのでしょうか?
これを行うべきではない理由
6. オプションの属性
interface Product { id: string type: 'digital' | 'physical' weightInKg?: number sizeInMb?: number }
どのようにすべきか
interface Product { id: string type: 'digital' | 'physical' } interface DigitalProduct extends Product { type: 'digital' sizeInMb: number } interface PhysicalProduct extends Product { type: 'physical' weightInKg: number }
なぜこれが悪い習慣なのでしょうか?
これを行うべきではない理由
sizeInMb があることを確認するなど、見逃される可能性のあるエラーをコンパイル時にチェックできます。
用一个字母命名泛型
function head<T> (arr: T[]): T | undefined { return arr[0] }
提供完整的描述性类型名称。
function head<Element> (arr: Element[]): Element | undefined { return arr[0] }
这种写法最早来源于C++的范型库,即使是 TS 的官方文档也在用一个字母的名称。它也可以更快地输入,只需要简单的敲下一个字母 T
就可以代替写全名。
通用类型变量也是变量,就像其他变量一样。当 IDE 开始向我们展示变量的类型细节时,我们已经慢慢放弃了用它们的名称描述来变量类型的想法。例如我们现在写代码用 const name ='Daniel'
,而不是 const strName ='Daniel'
。同样,一个字母的变量名通常会令人费解,因为不看声明就很难理解它们的含义。
通过直接将值传给 if
语句来检查是否定义了值。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
明确检查我们所关心的状况。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
编写简短的检测代码看起来更加简洁,使我们能够避免思考实际想要检测的内容。
也许我们应该考虑一下实际要检查的内容。例如上面的例子以不同的方式处理 countOfNewMessages
为 0
的情况。
将非布尔值转换为布尔值。
function createNewMessagesResponse (countOfNewMessages?: number) { if (!!countOfNewMessages) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
明确检查我们所关心的状况。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
对某些人而言,理解 !!
就像是进入 JavaScript 世界的入门仪式。它看起来简短而简洁,如果你对它已经非常习惯了,就会知道它的含义。这是将任意值转换为布尔值的便捷方式。尤其是在如果虚值之间没有明确的语义界限时,例如 null
、undefined
和 ''
。
与很多编码时的便捷方式一样,使用 !!
实际上是混淆了代码的真实含义。这使得新开发人员很难理解代码,无论是对一般开发人员来说还是对 JavaScript 来说都是新手。也很容易引入细微的错误。在对“非布尔类型的值”进行布尔检查时 countOfNewMessages
为 0
的问题在使用 !!
时仍然会存在。
!= null
棒棒运算符的小弟 ! = null
使我们能同时检查 null
和 undefined
。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages != null) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
明确检查我们所关心的状况。
function createNewMessagesResponse (countOfNewMessages?: number) { if (countOfNewMessages !== undefined) { return `You have ${countOfNewMessages} new messages` } return 'Error: Could not retrieve number of new messages' }
如果你的代码在 null
和 undefined
之间没有明显的区别,那么 != null
有助于简化对这两种可能性的检查。
尽管 null
在 JavaScript早期很麻烦,但 TypeScript 处于 strict
模式时,它却可以成为这种语言中宝贵的工具。一种常见模式是将 null
值定义为不存在的事物,将 undefined
定义为未知的事物,例如 user.firstName === null
可能意味着用户实际上没有名字,而 user.firstName === undefined
只是意味着我们尚未询问该用户(而 user.firstName ===
的意思是字面意思是 ''
。
原文:https://startup-cto.net/10-bad-typescript-habits-to-break-this-year/
作者:Daniel Bartholomae
译文地址:https://segmentfault.com/a/1190000039368534
更多编程相关知识,请访问:编程入门!!
以上がTypeScript でコードを書くときにやめるべき 10 の悪い習慣の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。