Appearance
Notes from Typescript type-challenges
Based on type-challenges here
Implement Pick
ts
// Create your own Pick implementation
// Goal
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>;
const todo: TodoPreview = {
title: 'Clean room',
completed: false,
};
// Answer
type MyPick<T, K extends keyof T> = { [Prop in K]: T[Prop] };
Notes:
K extends keyof T
ensures thatK
passed in coincides with object keys inT
Prop in K
:in
keyword iterates through the union types inK
. Important to note that thein
keyword is only able to iterate though union typesProp
is simply a placeholder variable representing each element in the union typesK
.Prop
can be replaced with any names.
T[Prop]
simply returns the type of the corresponding value in ObjectT
, e.g. the type ofTodo.title
.
Tuple to Object
ts
// Convert a tuple type to an object type
// Goal
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const;
const result: TupleToObject<typeof tuple> = {
tesla: 'tesla',
'model 3': 'model 3',
'model X': 'model X',
'model Y': 'model Y',
};
// Answer
type TupleToObject<T extends readonly string[]> = { [Prop in T[number]]: Prop };
Notes:
ts
const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const;
typeof tuple;
// Equals the exact array ['tesla', 'model 3', 'model X', 'model Y']
type TeslaModel = (typeof tuple)[number];
// Equals the possible values, i.e. the union types 'tesla' | 'model 3' | 'model X' | 'model Y'
T extends readonly string[]
becausetypeof tuple
equals an array with exacting elements.Prop in T[number]
works becauseT[number]
produces union types, allowingin
to iterate through it.
Implement Exclude
ts
// Create your own Exclude implementation
// Goal
type A = 'a' | 'b' | 'c';
type B = 'a';
type MyExclude<A, B> = 'b' | 'c';
// Answer
type MyExclude<T, U> = T extends U ? never : T;
Access a Wrapped Type
ts
// Goal
type X = Promise<string>;
type Y = Promise<{ field: number }>;
Awaited<X>;
// Awaited utility should return `string` type
Awaited<Y>;
// Awaited utility should return `{field: number}` type
// Answer
type Awaited<T extends Promise<any>> = T extends Promise<infer U> ? U : never;
Notes:
- There is no way to directly access a nested type. The approach here makes use of
infer
keyword to see if the nested type can be figured out, and uses that.
Concat Types
ts
// Write a concat type utility that produces the following result
type Result = Concat<[1], [2]>; // expected to be [1, 2]
// Answer
type Concat<T extends any[], U extends any[]> = [...T, ...U];