preface

I haven’t written an article for nearly a month. I mainly want to sort out and review this month. I plan to start job hunting in the middle of next month in Shenzhen. My lot

I’ve been working with TypeScript for almost a year now. Here are some tips and tips for working with TypeScript.

This article is for those who are familiar with TypeScript or have been using it for a while.

For those unfamiliar with TypeScript basics, check out this article: Getting Started with TypeScript

The operator

Type the alias

Used to give a type a new name

type Props = TextProps
Copy the code

keyof

Used to get all keys of a type whose return type is the union type.

interface Person {
  name: string
  age: number
}

type PersonKey = keyof Person // "name" | "age"
Copy the code

The joint type

And logic “| |” said it was for multiple types of any one

For example, when you write a Button component:

export type ButtonSize = 'lg' | 'md' | 'sm'
Copy the code

Cross type

Combine multiple types into a single type

For example, when you define the Props type for a new React component, you need a set of other properties

type Props = TypographyProps & ColorProps & SpaceProps
Copy the code

extends

The main effect is to add generic constraints

interface WithLength {
  length: number
}
// extends extends
function logger<T extends WithLength> (val: T) {
  console.log(val.length)
}
logger('hello')
logger([1.2.3])
Logger (true) // Error has no length attribute
Copy the code

typeof

Typeof is the type that gets an object/instance

interface Person {
  name: string
  age: number
}
const person1: Person = { name: 'monkey'.age: 18 }
const person2: typeof person1 = { name: 'jacky'.age: 24 } // By compiling
Copy the code

Generic tool types

Partial

Make all attributes of a type optional.

// Implementation: All changes optional
type Partial<T> = {
  [P inkeyof T]? : T[P] }Copy the code

example

interface Animal {
  canFly: boolean
  canSwim: boolean
}

// Change optional, you can assign only some attributes
let animal: Partial<Animal> = {
  canFly: false,}Copy the code

Readonly

It receives a generic T that marks all of its attributes as read-only

// Implementation: All become read-only
type Readonly<T> = {
  readonly [P in keyof T]: T[P]
}
Copy the code
interface Person {
  name: string
  age: number
}

let person: Readonly<Person> = {
  name: 'jacky'.age: 24,
}
person.name = 'jack' // Cannot assign to 'name' because it is a read-only property.
Copy the code

Required

Make all attributes of a type mandatory.

// Implementation: all changes are required
type Required<T> = {
  [P inkeyof T]-? : T[P] }Copy the code
interfacePerson { name? :stringage? :number
}

// Property 'age' is missing in type '{ name: string; }' but required in type 'Required<Person>'.
let person: Required<Person> = {
  name: 'jacky'.// An error occurs when the age attribute is not written
}
Copy the code

Record

// Implementation: all attribute values in K are converted to type T
type Record<K extends keyof any, T> = {
  [P in K]: T
}
Copy the code

The type generated by Record has an attribute that exists in type K and has a value of type T

interface DatabaseInfo {
  id: string
}

type DataSource = 'user' | 'detail' | 'list'

const x: Record<DataSource, DatabaseInfo> = {
  user: { id: '1' },
  detail: { id: '2' },
  list: { id: '3'}},Copy the code

Pick

// Implementation: Construct a Type by selecting a collection of property Keys from Type
type Pick<T, K extends keyof T> = {
  [P in K]: T[P]
}
Copy the code

Used to extract some properties of the interface

interface Animal {
  canFly: boolean
  canSwim: boolean
}

let person: Pick<Animal, 'canSwim'> = {
  canSwim: true,}Copy the code

Exclude

// Implementation: return if the type in T does not exist in U, otherwise not
type Exclude<T, U> = T extends U ? never : T
Copy the code

Remove a type that belongs to another type

interface Programmer {
  name: string
  age: number
  isWork: boolean
  isStudy: boolean
}

interface Student {
  name: string
  age: number
  isStudy: boolean
}

type ExcludeKeys = Exclude<keyof Programmer, keyof Student>
// type ExcludeKeys = "isWork"
Copy the code

Omit

// Implement: remove key pairs of type T containing K.
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
Copy the code

It works the opposite of Pick, and is easy to understand by looking directly at the code

interface Animal {
  canFly: boolean
  canSwim: boolean
}

let person1: Pick<Animal, 'canSwim'> = {
  canSwim: true,}let person2: Omit<Animal, 'canFly'> = {
  canSwim: true,}Copy the code

ReturnType

// Implementation: get T type (function) corresponding return value type
type ReturnType<T extends(... args:any) = >any> = T extends(... args:any) => infer R ? R : any
Copy the code

Gets the return value type of the function

function bar(x: string | number) :string | number {
  return 'hello'
}
type FooType = ReturnType<typeof bar> // string | number
Copy the code

The operator

Optional chain operator

The optional chain operator (? .). Allows you to read the value of a property located deep in the chain of connected objects without explicitly validating that each reference in the chain is valid. Certain expressions can be stopped immediately if null or undefined is encountered

This is often used in projects and works well.

Let’s say our data is all coming back from our API, so let’s say we have this set of data

// The data is returned after the API is requested
{
  data: {
    name: 'jacky'.age: 24.address: {
      city: 'shenzhen',,}}}Copy the code

Front end to value after receiving apiRequestResult. Data. Address. City, normal to the value, if there is no return address this object background GG, then an error:

TypeError: Cannot read property 'city' of undefined
Copy the code

This time need front-end processing, such as the most direct is

apiRequestResult && apiRequestResult.data && data.address && data.address.city
Copy the code

Or the Lodash library approach will work

import * as _ from 'lodash'
const city = _.get(apiRequestResult, 'apiRequestResult.data.address.city'.undefined)
Copy the code

The optional chain operator of TS can be used if there are many objects in the project.

apiRequestResult? .data? .address? .cityCopy the code

The above code automatically checks if the object is null or undefined, and returns undefined immediately, thus stopping certain expressions without error.

This operator is also used when you use the ref wrapper in React to determine whether elements contain XX elements

constisClickAway = ! childRef.current? .contains? .(e.target)Copy the code

Null-value merge operator

Null-value merge operator (??) Is a logical operator that returns the right-hand operand if the left-hand operand is null or undefined, otherwise returns the left-hand operand.

And | | operators are similar, but the | | is a Boolean logical operators, the left operand are forced into Boolean value for evaluation. 0, “, NaN, null, undefined will not be returned.

const foo1 = null
const foo2 = 12
const foo3 = 'hello'

const res1 = foo1 ?? 'value' // 'value'
const res2 = foo2 ?? 'value' / / 12
const res3 = foo3 ?? 'value' // 'hello'
Copy the code

Real development can be mixed, right? And??

const title = document.getElementById("title")? .textContent ?? "";Copy the code

Non-null assertion operator

When the type checker is unable to determine the type in context, this operator (!) Can be used after a variable or function name to assert that the operation object is non-null and non-undefined. However, it is generally not recommended

And this applies if we’re pretty sure that we don’t return a null value

function print(name: string | undefined) {
  let myName: string = 'jacky'
  // Type 'string | undefined' is not assignable to type 'string'.
  // Type 'undefined' is not assignable to type 'string'
  myName = name
}
Copy the code

To resolve this error, add judgment

function print(name: string | undefined) {
  let myName: string = 'jacky'
  if (name) {
    myName = name
  }
}
Copy the code

But that makes writing code a little bit more verbose, and if you’re pretty sure it’s not null, use a non-null assertion operator

function print(name: string | undefined) {
  let myName: string = 'jacky'
  myName = name!
}
Copy the code

This reduces redundant code judgments

Application of details in a project

Try to avoid any

Avoid any, but can’t check? You can use unknown instead

It’s not a very good example, because the following example is a forcible correction of the error itself. (xx as unknown) as SomeType (xx as unknown) as SomeType (xx as unknown

const metaData = {
  description: 'xxxx',}interface MetaType {
  desc: string
}

function handleMeta(data: MetaType) :void {}

// Both methods will return an error
// handleMeta(metaData)
// handleMeta(metaData as MetaType)

// The type check can be used to avoid any errors, and the static check function can be retained.
handleMeta((metaData as unknown) as MetaType)
Copy the code

Indexable type

Generally used to constrain objects and arrays

interface StringObject {
  // Key is of type string, representing the object
  // Restrict value to string
  [key: string] :string
}
let obj: StringObject = {
  name: 'jacky'.age: 24.Type 'number' is not assignable to Type 'string'.
}
Copy the code
interface StringArr {
  // Key is of type number, representing an array
  // Restrict value to string
  [key: number] :string
}
let arr: StringArr = ['name'.'jacky']
Copy the code

annotation

The editor will have a better hint if the TS type is flagged by comments in the form of /** */

/** Animal common props */
interface Animal {
  /** like animal special skill */
  feature: string
}

const cat: Animal = {
  feature: 'running',}Copy the code

ts-ignore

Again, use unknown instead of any whenever possible

If any is disabled in your project, ts-ignore is a much bigger potential code quality problem than any.

Disabled but some places do need to use ignore, the best comment to add more reasons.

For example, some function unit test files, test cases deliberately passed incorrect data types, and so on, sometimes are forced to report errors.

// @ts-ignore intentionally for test
Copy the code


  • If you feel good, welcome star, give me a little encouragement to continue writing ~