TS- tuples are converted to objects

Topic link

Pass in a tuple type and convert the tuple type to an object type whose keys/values are iterated from the tuple.

Such as:

const tuple = ['tesla'.'model 3'.'model X'.'model Y'] as const

const result: TupleToObject<typeof tuple> 
// expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
Copy the code

I. Key word description

tuples

Tuple official link

In TypeScript, tuple types are used to represent arrays with known numbers and types of elements. Each element does not have to be of the same type.

Arrays merge objects of the same type, while tuples merge objects of different types.

An ancestor can be used to determine the data type of an element, but do not go beyond the scope. A primitive can be thought of as a fixed length, and beyond the scope does not guarantee its type.

The typeof keyword

In TypeScript, the typeof operator can be used to retrieve the typeof a variable or object.

interface People {
  name: string;
  age: number;
}

const me: People = { name: "zzk".age: 23 };
type Me = typeof me; // type Me = People
Copy the code

In the above code, we get the typeof the me variable using the typeof operator and assign it to the me variable, after which we can use the me type:

const oneGod: Me  = { name: "one".age: 24 }
Copy the code

You can do the same for nested objects:

const otherPeople = {
    name: "one".age: 24.address: {
      province: 'shandong'.city: 'Qingdao'}}type OtherPeople = typeof otherPeople;
/* type OtherPeople = { name: string; age: number; address: { province: string; city: string; }; } * /
Copy the code

In addition to retrieving the structural typeof an object, the typeof operator can also be used to retrieve the typeof a function object, for example:

function toArray(x: number) :Array<number> {
  return [x];
}

type Func = typeof toArray; // -> (x: number) => number[]
Copy the code

The as keyword

Type assertion official link

Sometimes you’ll find that you know more about a value than TypeScript does. Usually this happens when you clearly know that an entity has a more exact type than its existing type.

Type assertions are a way of telling the compiler, “Trust me, I know what I’m doing.” Type assertion is like conversion in other languages, but without special data checking and deconstruction. It has no run-time impact, only at compile time. TypeScript assumes that you, the programmer, have done the necessary checks.

Type assertions come in two forms. The first is the Angle bracket syntax:

let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length;
Copy the code

The other is the as syntax:

let someValue: any = "this is a string";

let strLength: number = (someValue as string).length;
Copy the code

Both forms have the same effect; However, when you use JSX in TypeScript, only AS syntax assertions are allowed.

Const assertion

TypeScript 3.4 introduces a new way of constructing literals, also known as const assertions. When we construct new literal expressions using const assertions, we can signal to the programming language the following:

  • No literal type in an expression should be extended;
  • Object literal property that will be usedreadonlyModification;
  • The array literal will becomereadonlyTuples.

Here’s an example of a const assertion:

let x = "hello" as const;
type X = typeof x; // type X = "hello"

let y = [10, 20] as const;
type Y = typeof y; // type Y = readonly [10, 20]

let z = { text: "hello" } as const;
type Z = typeof z; // let z: { readonly text: "hello"; }
Copy the code

When a const assertion is applied to an array literal, it becomes a readonly tuple. After that, we can also use the typeof operator to get the union typeof the element values in the tuple as follows:

type Data = typeof y[number]; // type Data = 10 | 20
Copy the code

The same applies to arrays containing reference types, such as arrays containing ordinary objects. Here’s a concrete example:

Const locales = [{locale: "zh-cn ", language:" Chinese "}, {locale: "en", language: "English"}] as const; // type Locale = "zh-CN" | "en" type Locale = typeof locales[number]["locale"];Copy the code

There are two additional considerations when using const assertions:

  1. constAssertions apply only to simple literal expressions
// A 'const' assertions can only be applied to references to enum members, // or string, number, boolean, array, Or object literals.let a = (math.random () < 0.5? 0 : 1) as const; // error let b = math.random () < 0.5? 0 as const : 1 as const;Copy the code
  1. constContext does not immediately convert the expression to be completely immutable
let arr = [1, 2, 3, 4]; let foo = { name: "foo", contents: arr, } as const; foo.name = "bar"; // error! foo.contents = []; // error! foo.contents.push(5); / /... works!Copy the code

Two, the use of tuples

Define a pair of tuples of string and number:

let tom: [string.number] = ['Tom'.25];
Copy the code

When assigning or accessing an element with a known index, the correct type is obtained:

let tom: [string.number];
tom[0] = 'Tom';
tom[1] = 25;

tom[0].slice(1);
tom[1].toFixed(2);
Copy the code

You can also assign only one of the items:

let tom: [string.number];
tom[0] = 'Tom';
Copy the code

However, when a tuple type variable is initialized or assigned directly, all items specified in the tuple type need to be supplied.

let tom: [string.number];
tom = ['Tom'.25];
let tom: [string.number];
tom = ['Tom'];

// Property '1' is missing in type '[string]' but required in type '[string, number]'.
Copy the code

Out of bounds element

When an out-of-bounds element is added, its type is limited to the combined type of each type in the tuple:

let tom: [string.number];
tom = ['Tom'.25];
tom.push('male');
tom.push(true);

// Argument of type 'true' is not assignable to parameter of type 'string | number'.
Copy the code

Third, antithesis

const tuple = ['tesla'.'model 3'.'model X'.'model Y'] as const

// ReadOnly, extends: When a const literal represents an object literal property, the property is modified with 'readonly'. Array literals become 'readonly' tuples. No literal types in expressions should be extended
//[K in T[number]] loop through each index in the array to convert index to key
type TupleToObject<T extends readonly any[]> = { [K in T[number]]: K }

const result: TupleToObject<typeof tuple> 
// expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}

Copy the code