In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article introduces the knowledge of "what are the bad habits of writing TypeScript code?". Many people will encounter such a dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
1. Do not use strict mode
(1) what does this habit look like
Tsconfig.json is not written in strict mode.
{"compilerOptions": {"target": "ES2015", "module": "commonjs"}}
(2) what should be done?
Simply enable strict mode:
{"compilerOptions": {"target": "ES2015", "module": "commonjs", "strict": true}}
(3) Why do you have this bad habit?
It takes time to introduce stricter rules into an existing code base.
(4) Why should not do this?
Stricter rules make it easier to maintain code in the future, saving you a lot of time.
two。 Use | | define default values
(1) what does this habit look like
Use the old | | default values for processing backups:
Function createBlogPost (text: string, author: string, date?: Date) {return {text: text, author: author, date: date | | new Date ()}}
(2) what should be done?
Use the new? Operator, or redefine the default value in the parameter.
Function createBlogPost (text: string, author: string, date: Date = new Date ()) return {text: text, author: author, date: date}}
(3) Why do you have this bad habit?
?? The operator was introduced only last year, and when you use a value in a long function, it can be difficult to set it as the parameter default.
(4) Why should not do this?
?? Different from | |? For null or undefined only, not for all imaginary values.
3. Feel free to use the any type
(1) what does this habit look like
When you are unsure of the structure, you can use the any type.
Async function loadProducts (): Promise {const response = await fetch ('https://api.mysite.com/products') const products: any = await response.json () return products})
(2) what should be done?
Change any place in your code that uses any to unknown
Async function loadProducts (): Promise {const response = await fetch ('https://api.mysite.com/products') const products: unknown = await response.json () return products as Product []})
(3) Why do you have this bad habit?
Any is convenient because it basically disables all type checking. Usually, any is used even in officially provided types. For example, the TypeScript team set the type of response.json () in the above example to Promise.
(4) Why should not do this?
It basically disables all types of checking. Anything that comes in through any will completely abandon all types of checks. This will make the error difficult to catch.
4. Val as SomeType
(1) what does this habit look like
Forcibly tell the compiler types that cannot be inferred.
Async function loadProducts (): Promise {const response = await fetch ('https://api.mysite.com/products') const products: unknown = await response.json () return products as Product []})
(2) what should be done?
This is the opportunity for Type Guard to use his talents.
Function isArrayOfProducts (obj: unknown): obj isProduct [] {return Array.isArray (obj) & & obj.every (isProduct)} function isProduct (obj: unknown): obj isProduct {return obj! = null & & typeof (obj as Product). Id = = 'string'} async function loadProducts (): Promise {const response = await fetch (' https://api.mysite.com/products') const products: unknown = await response.json () if (! isArrayOfProducts) ) {throw new TypeError ('Received malformed products API response')} return products}
(3) Why do you have this bad habit?
When moving from JavaScript to TypeScript, existing code bases often make assumptions about types that the TypeScript compiler cannot automatically infer. At this point, you can speed up the conversion through as SomeOtherType without having to modify the settings in tsconfig.
(4) Why should not do this?
Type Guard ensures that all checks are clear.
5. As any in Test
(1) what does this habit look like
Create incomplete use cases when writing tests.
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)}
(2) what should be done?
If you need to simulate test data, move the simulation logic next to the object you want to simulate and make it reusable.
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)}
(3) Why do you have this bad habit?
When writing tests for code that does not yet have extensive test coverage, there is usually a complex big data structure, but only some of the specific functions to be tested are needed. You don't have to worry about other attributes in the short term.
(4) Why should not do this?
In some cases, the code under test relies on attributes that we previously considered unimportant, and then all tests for that feature need to be updated.
6. Optional attribute
(1) what does this habit look like
Mark attributes as optional, even if they sometimes do not exist.
Interface Product {id: string type: 'digital' |' physical' weightInKg?: number sizeInMb?: number}
(2) what should be done?
Identify which combinations exist and which do not.
Interface Product {id: string type: 'digital' |' physical'} interface DigitalProduct extends Product {type: 'digital' sizeInMb: number} interface PhysicalProduct extends Product {type:' physical' weightInKg: number}
(3) Why do you have this bad habit?
It is easier to mark attributes as optional rather than split types and produces less code. It also requires a deeper understanding of the product being built and may limit the use of code if changes are made to the design of the product.
(4) Why should not do this?
The biggest advantage of a type system is that compile-time checks can be used instead of run-time checks. With more explicit types, you can check for errors that may go unnoticed at compile time, such as ensuring that each DigitalProduct has a sizeInMb.
7. Use one letter to pass through the world
(1) what does this habit look like
Name generics with one letter
Function head (arr: t []): t | undefined {return arr [0]}
(2) what should be done?
Provide a complete descriptive type name.
Function head (arr: Element []): Element | undefined {return arr [0]}
(3) Why do you have this bad habit?
It was originally written in C++ 's stereotype library, and even official TS documents use an one-letter name. It can also be typed faster, simply typing the letter T instead of writing the full name.
(4) Why should not do this?
Generic type variables are also variables, just like other variables. When IDE began to show us the type details of variables, we slowly gave up the idea of using their names to describe variable types. For example, we now write code with const name = 'Daniel', instead of const strName =' Daniel'. Similarly, one-letter variable names are often confusing because it is difficult to understand their meaning without looking at the declaration.
8. Boolean check for values of non-Boolean type
(1) what does this habit look like
Check whether a value is defined by passing the value directly to the if statement.
Function createNewMessagesResponse (countOfNewMessages?: number) {if (countOfNewMessages) {return `You have ${countOfNewMessages} new messages`} return 'Error: Could not retrieve number of new messages'}
(2) what should be done?
Check clearly what we are concerned about.
Function createNewMessagesResponse (countOfNewMessages?: number) {if (countOfNewMessages! = = undefined) {return `You have ${countOfNewMessages} new messages`} return 'Error: Could not retrieve number of new messages'}
(3) Why do you have this bad habit?
Writing short detection code looks more concise, allowing us to avoid thinking about what we actually want to test.
(4) Why should not do this?
Maybe we should consider what we actually want to check. For example, the above example deals with the case where countOfNewMessages is 0 in different ways.
9. "awesome" operator
(1) what does this habit look like
Converts non-Boolean values to Boolean values.
Function createNewMessagesResponse (countOfNewMessages?: number) {if (!! countOfNewMessages) {return `You have ${countOfNewMessages} new messages`} return 'Error: Could not retrieve number of new messages'}
(2) how to make it clear
Make sure to check what we are concerned about.
Function createNewMessagesResponse (countOfNewMessages?: number) {if (countOfNewMessages! = = undefined) {return `You have ${countOfNewMessages} new messages`} return 'Error: Could not retrieve number of new messages'}
(3) Why do you have this bad habit?
For some people, understand! It's like an introduction to the world of JavaScript. It looks short and concise, and if you're used to it, you'll know what it means. This is a convenient way to convert any value to a Boolean value. Especially if there are no clear semantic boundaries between imaginary values, such as null, undefined, and''.
(4) Why should not do this?
Like many convenient ways to code, use! It actually confuses the true meaning of the code. This makes it difficult for new developers to understand the code, both for the average developer and for JavaScript. It is also easy to introduce minor errors. The problem that countOfNewMessages is 0 is being used in Boolean checking for "non-Boolean values". Will still exist.
10.! = null
(1) what does this habit look like
The younger brother of the stick operator! = null enables us to check both null and undefined.
Function createNewMessagesResponse (countOfNewMessages?: number) {if (countOfNewMessages! = null) {return `You have ${countOfNewMessages} new messages`} return 'Error: Could not retrieve number of new messages'}
(2) what should be done?
Check clearly what we are concerned about.
Function createNewMessagesResponse (countOfNewMessages?: number) {if (countOfNewMessages! = = undefined) {return `You have ${countOfNewMessages} new messages`} return 'Error: Could not retrieve number of new messages'
(3) Why do you have this bad habit?
If there is no obvious difference between null and undefined in your code, then! = null helps simplify the inspection of both possibilities.
(4) Why should not do this?
Although null was troublesome in the early days of JavaScript, when TypeScript was in strict mode, it could be a valuable tool in the language. A common pattern is to define the null value as something that does not exist, and the undefined as something unknown, for example, user.firstName = = null may mean that the user actually does not have a name, while user.firstName = = undefined simply means that we have not asked the user (and user.firstName = = means literally''.
This is the end of the content of "what are the bad habits of writing TypeScript code". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.