SoFunction
Updated on 2025-04-06

Summary of some places that spend time on TypeScript

Record some places where you spend time on Ts.

(I'll complain first: * really has everything, Baidu really can't use it)

pit

Compatibility misunderstandings of assertions, such as "a" as "b" codes will not report errors.

Inconsistent behavior between interface and type (I thought I wrote the wrong type in my first encounter, and looked confused):

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

type It seems that there is no differencetrue = Type extends Interface ? Type extends Interface ? true : false : false

type Points = {
  [key: string]: Points
} | string

type test<T> = T extends Points ? true : false
type This istrue = test<Type>
type This isfalse = test<Interface>

There is an official statement on github that this is deliberately left with a pitfall. It is said that because the interface is extensible (automatically merged with the same name), it is inconvenient to detect.

When using generics to implement the effect of function overloading, in the implementation of the function, generics do not have specific constraints, resulting in the use of as-force assertions often need to be used.

//It's almost the same, the following code is too lazy to actually test 🙃
//fns is a function index table, and TFns is the const type of the index tablefunction Overload failed<T extends keyof TFns>(fn:T, params: Parameters<fns[T]>){
    fns[fn](...params)//In the implementation, the joint type will not be reduced, so an error will be reported    //The error should be like the parameter of method 1 cannot be passed to method 2.}
//But when used externally, it doesn't matter if you match the semantics of the type.

Extended operators do not match the intuitive feeling:[...string[], number] is in line with the intuition when used (requiring the number element at the end of the array), but [...string[], null, ...object[], number] does not work, and will not be in order or errors.The new version of Ts has added rules that prohibit continuous deconstruction, and this type is not allowed to be written directly.

Actually, there is a solution here, but the type you wrote is simply unavailable (a few dozen lines, including a large number of extends as if judgments of type), so I won't post the following code:

//Required types: [...number[], "middle-element", ...boolean[]]//The above writing method is invalid, it just shows what the type code below is used for (implementing the type constraints shown 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 Report an error = check(false, "middle-element", 2)

Advanced operation

Object name remapping:

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

Union type split: Use the infer keyword to achieve splitting of union type.

//"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) Direct `keyof Obj extends infer K` cannot be divided into union types, for unknown reasons (I am 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 Type:

  • Actual (non-type) parameters sometimes need to be explicitly defined as tuple types through as const.
  • Tuple type can get the exact length through the tuple ["length"] instead of number.
  • When using tuple types through generic parameters, sometimes you need to write them into tuples by adding []| extends []|any[] to avoid being parsed into ordinary indefinitely long array types.

Recursive type: Use...infer More to implement recursive array types.

type Converter<T> = T extends string ? "str" : null
//When you go in, it's a [string,number,string], and when you come out, it's ["str",null,"str"]type recursion<
        Input source extends any[],
        Internal type cache extends any[] = []
    > = Input source extends [any, ...infer Remaining elements] ?
        recursion<Remaining elements, [...Internal type cache, Converter<Input source[0]>]>
        : Input source

Spoken

  • & can be used instead of extends for type. The interface can merge types with the same name, and there is no difference between them.
  • ts has rich built-in types, so choose a few examples:
    • ReturnType<function type>, gets the type of return value of the function type.
    • Uncapitalize<String>, locks the first letter of the input string type to lowercase (others include initials, all lowercase, and all uppercase).

Newbie recommends going to the official website to translate documents.

After entering the ts pit, you can pay attention to the new features (playing method) brought by the next version update.

Summarize

This is the article about the summary of the places that spend time on TypeScript. For more relevant content on ts, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!