A summary of some of the places where I spent time on TypeScript

A summary of some of the places where I spent time on TypeScript

Record some of the places where you spent time on ts.

(First of all, let me complain: stackoverflow really has everything, but Baidu is really useless)

pit

Compatibility misunderstanding of as assertion, such as "a" as "b" will not report an error.

Inconsistent behavior between interface and type (when I first encountered it, I thought I wrote the wrong type and was confused):

type Type = {
  key: "value"
}
interface Interface {
  key: "value"
}

type seems to be no different, both are true = Type extends Interface ? Type extends Interface ? true : false : false

type pit point = {
  [key: string]: pit point} | string

type test<T> = T extends pitfall? true : false
type This is true = Test <Type>
type This is false = Test <Interface>

There is an official explanation on GitHub that this pit was left intentionally. It is said that because the interface is extensible (the same name is automatically merged), it is inconvenient to detect.

When using generics to implement function overloading, in the implementation of the function, it is often necessary to use as forced assertions because generics do not have specific constraints.

//That's about it. I'm too lazy to actually test the following code 🙃

//fns is a function index table, TFns is the const type of the index table. Function overloading failed <T extends keyof TFns>(fn:T, params: Parameters<fns[T]>){
    fns[fn](...params) //In the implementation, the union type will not be narrowed, so an error will be reported //The error should be something like "cannot pass the parameters of method 1 to method 2"}
//But when used externally, it doesn't matter if the semantics of the type are met

The spread operator is not intuitive: [...string[], number] is intuitive to use (requiring a number element at the end of the array), but [...string[], null, ...object[], number] is not intuitive and will not report an error. The new version of ts adds a rule prohibiting continuous deconstruction, so this type of writing is not allowed.

Actually, there is a solution here, but the type written is simply unreadable (dozens of lines, including a large number of extends acting as type if judgments), so I will not post it. The code is posted below:

// Required types: [...number[], "middle-element", ...boolean[]] 
//The above is invalid, it just indicates what the following type code is used for (to implement the type constraints indicated above)

type Elem = number | boolean | "middle-element";

type Last<T extends any[]> = T extends [infer _]
  ? never
  : T extends [...infer _, infer Tl]
  ? Tl
  : never

type HandleEmpty<T extends any[], Data> = T['length'] extends 0 ? never : Data

type Validation<Params extends any[], Cache extends Elem[] = []> =
  Params extends []
  ? Cache['length'] extends 0
  ? never
  : Cache
  : Params extends [infer Fst, ...infer Rest]
  ? Cache extends []
  ? Fst extends number
  ? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
  : never
  : Fst extends number
  ? Last<Cache> extends number
  ? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
  : never
  : Fst extends "middle-element"
  ? Last<Cache> extends number
  ? HandleEmpty<Rest, Validation<Rest, [...Cache, Fst]>>
  : never
  : "middle-element" extends Cache[number]
  ? Fst extends boolean
  ? Validation<Rest, [...Cache, Fst]>
  : never
  : never
  : never

type IsNever<T> = [T] extends [never] ? true : false;

function check<
  Params extends Elem[],
  IsValid extends Validation<Params>
>(...arr: IsNever<IsValid> extends true ? [never] : [...Params]) {
  return arr
}

const normal = check(1, 'middle-element', false)
const error = check(false, "middle-element", 2)

Advanced Operations

Object name remapping:

//{ "new-a":any; "new-b":any }
type remap = {
    [K in "a" | "b" as `new-${K}`]: any
}

Splitting of union types: The infer keyword can be used to split union types.

//"a1"|"b2"
type split successfully <_Keys = keyof { a: 1, b: 2 }> = _Keys extends infer K ?
    `${Extract<K, string>}${{ a: 1, b: 2 }[Extract<K, _Keys>]}`
    : never

// Note: (as of ts4.4.4) Directly `keyof Obj extends infer K` cannot split the union type, the reason is unknown (too lazy to check 😁).
//The result is "a1"|"a2"|"b1"|"b2"
type split failed = keyof { a: 1, b: 2 } extends infer K ?
    `${Extract<K, string>}${{ a: 1, b: 2 }[Extract<K, "a" | "b">]}`
    : never

Tuple types:

  • The actual (non-type) parameters sometimes need to be explicitly declared as tuple types using as const.
  • Tuple types can get the exact length instead of the number through tuple["length"].
  • When a tuple type is used through a generic parameter, it is sometimes necessary to add []| and write it as a tuple extends []|any[] to avoid being parsed as a normal indefinite-length array type.

Recursive types: Use ...infer More to implement recursion on array types.

type Converter<T> = T extends string ? "str" ​​: null
//It goes in as [string,number,string], and comes out as ["str",null,"str"]
type recursion<
        Input source extends any[],
        The internal type cache extends any[] = []
    > = input source extends [any, ...infer remaining elements] ?
        Recursion <remaining elements, [...internal type cache, converter <input source [0]>]>
        : Input Source

Odds and Ends

  • & can be used instead of extends for type. Interface has no other difference except that it can merge types with the same name.
  • ts has a rich set of built-in types, here are a few examples:
    • ReturnType<function type>, gets the type of the return value of the function type.
    • Uncapitalize <string>, lock the first letter of the input string type to lowercase (other options include first letter capitalization, all lowercase, and all uppercase).

It is recommended for beginners to go to the official website to read the documents.

After getting into ts, you can pay attention to the new features (gameplay) brought by version updates.

Summarize

This is the end of this article summarizing the places where I spent time on TypeScript. For more relevant content about where I spent time on TypeScript, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope everyone will support 123WORDPRESS.COM in the future!

<<:  Detailed explanation of Tomcat core components and application architecture

>>:  HTML tags list and usage instructions

Recommend

Detailed explanation of Vue's calculated properties

1. What is a calculated attribute? In plain words...

js implements array flattening

Table of contents How to flatten an array 1. Usin...

This article will help you understand the life cycle in Vue

Table of contents 1. beforeCreate & created 2...

SQL method for calculating timestamp difference

SQL method for calculating timestamp difference O...

Detailed description of component-based front-end development process

Background <br />Students who work on the fr...

HTML form tag usage learning tutorial

Forms in HTML can be used to collect various type...

Best Practices for Sharing React Code

When any project develops to a certain complexity...

Weather icon animation effect implemented by CSS3

Achieve results Implementation Code html <div ...

CSS stacking and z-index example code

Cascading and Cascading Levels HTML elements are ...

Summary of MySQL's commonly used concatenation statements

Preface: In MySQL, the CONCAT() function is used ...

10 skills that make front-end developers worth millions

The skills that front-end developers need to mast...

5 Simple XHTML Web Forms for Web Design

Simple XHTML web form in web design 5. Technique ...

VMware WorkStation 14 pro installation Ubuntu 17.04 tutorial

This article records the specific method of insta...