Your Code Here 下面自行实现
使用vscode刷题
热身题
13. Hello World
// ============= Test Cases =============
import type { Equal, Expect, NotAny } from "./test-utils";
type cases = [Expect<NotAny<HelloWorld>>, Expect<Equal<HelloWorld, string>>];
// ============= Your Code Here =============
type HelloWorld = string; // expected to be a string
容易题
4. Pick
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<Expected1, MyPick<Todo, "title">>>,
Expect<Equal<Expected2, MyPick<Todo, "title" | "completed">>>,
// @ts-expect-error
MyPick<Todo, "title" | "completed" | "invalid">
];
interface Todo {
title: string;
description: string;
completed: boolean;
}
interface Expected1 {
title: string;
}
interface Expected2 {
title: string;
completed: boolean;
}
// ============= Your Code Here =============
type MyPick<T, K extends keyof T> = { [Key in K]: T[Key] };
7. Readonly
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [Expect<Equal<MyReadonly<Todo1>, Readonly<Todo1>>>];
interface Todo1 {
title: string;
description: string;
completed: boolean;
meta: {
author: string;
};
}
// ============= Your Code Here =============
type MyReadonly<T> = { readonly [key in keyof T]: T[key] };
11. Tuple to Object
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
const tuple = ["tesla", "model 3", "model X", "model Y"] as const;
const tupleNumber = [1, 2, 3, 4] as const;
const sym1 = Symbol(1);
const sym2 = Symbol(2);
const tupleSymbol = [sym1, sym2] as const;
const tupleMix = [1, "2", 3, "4", sym1] as const;
type cases = [
Expect<
Equal<
TupleToObject<typeof tuple>,
{
tesla: "tesla";
"model 3": "model 3";
"model X": "model X";
"model Y": "model Y";
}
>
>,
Expect<Equal<TupleToObject<typeof tupleNumber>, { 1: 1; 2: 2; 3: 3; 4: 4 }>>,
Expect<
Equal<
TupleToObject<typeof tupleSymbol>,
{ [sym1]: typeof sym1; [sym2]: typeof sym2 }
>
>,
Expect<
Equal<
TupleToObject<typeof tupleMix>,
{ 1: 1; "2": "2"; 3: 3; "4": "4"; [sym1]: typeof sym1 }
>
>
];
// @ts-expect-error
type error = TupleToObject<[[1, 2], {}]>;
// ============= Your Code Here =============
type TupleToObject<T extends readonly (string | number | symbol)[]> = {
[Key in T[number]]: Key;
};
14. First of Array
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<First<[3, 2, 1]>, 3>>,
Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,
Expect<Equal<First<[]>, never>>,
Expect<Equal<First<[undefined]>, undefined>>
];
type errors = [
// @ts-expect-error
First<"notArray">,
// @ts-expect-error
First<{ 0: "arrayLike" }>
];
// ============= Your Code Here =============
type First<T extends any[]> = T extends [] ? never : T[0];
18. Length of Tuple
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
const tesla = ["tesla", "model 3", "model X", "model Y"] as const;
const spaceX = [
"FALCON 9",
"FALCON HEAVY",
"DRAGON",
"STARSHIP",
"HUMAN SPACEFLIGHT",
] as const;
type cases = [
Expect<Equal<Length<typeof tesla>, 4>>,
Expect<Equal<Length<typeof spaceX>, 5>>,
// @ts-expect-error
Length<5>,
// @ts-expect-error
Length<"hello world">
];
// ============= Your Code Here =============
type Length<T extends readonly any[]> = T["length"];
43. Exclude
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<MyExclude<"a" | "b" | "c", "a">, "b" | "c">>,
Expect<Equal<MyExclude<"a" | "b" | "c", "a" | "b">, "c">>,
Expect<
Equal<MyExclude<string | number | (() => void), Function>, string | number>
>
];
// ============= Your Code Here =============
type MyExclude<T, U> = T extends U ? never : T;
189. Awaited
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type X = Promise<string>;
type Y = Promise<{ field: number }>;
type Z = Promise<Promise<string | number>>;
type Z1 = Promise<Promise<Promise<string | boolean>>>;
type T = { then: (onfulfilled: (arg: number) => any) => any };
type cases = [
Expect<Equal<MyAwaited<X>, string>>,
Expect<Equal<MyAwaited<Y>, { field: number }>>,
Expect<Equal<MyAwaited<Z>, string | number>>,
Expect<Equal<MyAwaited<Z1>, string | boolean>>,
Expect<Equal<MyAwaited<T>, number>>
];
// @ts-expect-error
type error = MyAwaited<number>;
// ============= Your Code Here =============
// type MyAwaited<
// T extends Promise<any> | { then: (onfulfilled: (arg: any) => any) => any }
// > = T extends Promise<infer R>
// ? R extends Promise<any>
// ? MyAwaited<R>
// : R
// : T extends { then: (onfulfilled: (arg: infer A) => any) => any }
// ? A
// : never;
type MyAwaited<T extends PromiseLike<any>> = T extends PromiseLike<infer R>
? R extends PromiseLike<any>
? MyAwaited<R>
: R
: never;
268. If
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<If<true, "a", "b">, "a">>,
Expect<Equal<If<false, "a", 2>, 2>>
];
// @ts-expect-error
type error = If<null, "a", "b">;
// ============= Your Code Here =============
type If<C extends boolean, T, F> = C extends true ? T : F;
533. Concat
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
const tuple = [1] as const;
type cases = [
Expect<Equal<Concat<[], []>, []>>,
Expect<Equal<Concat<[], [1]>, [1]>>,
Expect<Equal<Concat<typeof tuple, typeof tuple>, [1, 1]>>,
Expect<Equal<Concat<[1, 2], [3, 4]>, [1, 2, 3, 4]>>,
Expect<
Equal<
Concat<["1", 2, "3"], [false, boolean, "4"]>,
["1", 2, "3", false, boolean, "4"]
>
>
];
// @ts-expect-error
type error = Concat<null, undefined>;
// ============= Your Code Here =============
type Concat<T extends readonly any[], U> = T extends readonly any[]
? U extends readonly any[]
? [...T, ...U]
: never
: never;
898. Includes
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<
Equal<Includes<["Kars", "Esidisi", "Wamuu", "Santana"], "Kars">, true>
>,
Expect<
Equal<Includes<["Kars", "Esidisi", "Wamuu", "Santana"], "Dio">, false>
>,
Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 7>, true>>,
Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 4>, false>>,
Expect<Equal<Includes<[1, 2, 3], 2>, true>>,
Expect<Equal<Includes<[1, 2, 3], 1>, true>>,
Expect<Equal<Includes<[{}], { a: "A" }>, false>>,
Expect<Equal<Includes<[boolean, 2, 3, 5, 6, 7], false>, false>>,
Expect<Equal<Includes<[true, 2, 3, 5, 6, 7], boolean>, false>>,
Expect<Equal<Includes<[false, 2, 3, 5, 6, 7], false>, true>>,
Expect<Equal<Includes<[{ a: "A" }], { readonly a: "A" }>, false>>,
Expect<Equal<Includes<[{ readonly a: "A" }], { a: "A" }>, false>>,
Expect<Equal<Includes<[1], 1 | 2>, false>>,
Expect<Equal<Includes<[1 | 2], 1>, false>>,
Expect<Equal<Includes<[null], undefined>, false>>,
Expect<Equal<Includes<[undefined], null>, false>>
];
// ============= Your Code Here =============
type Includes<T extends readonly any[], U> = T extends [infer F, ...infer R]
? Equal<F, U> extends true
? true
: Includes<R, U>
: false;
3057. Push
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<Push<[], 1>, [1]>>,
Expect<Equal<Push<[1, 2], "3">, [1, 2, "3"]>>,
Expect<Equal<Push<["1", 2, "3"], boolean>, ["1", 2, "3", boolean]>>
];
// ============= Your Code Here =============
type Push<T, U> = T extends any[] ? [...T, U] : never;
3060. Unshift
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<Unshift<[], 1>, [1]>>,
Expect<Equal<Unshift<[1, 2], 0>, [0, 1, 2]>>,
Expect<Equal<Unshift<["1", 2, "3"], boolean>, [boolean, "1", 2, "3"]>>
];
// ============= Your Code Here =============
type Unshift<T, U> = T extends any[] ? [U, ...T] : never;
3312. Parameters
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
const foo = (arg1: string, arg2: number): void => {};
const bar = (arg1: boolean, arg2: { a: "A" }): void => {};
const baz = (): void => {};
type cases = [
Expect<Equal<MyParameters<typeof foo>, [string, number]>>,
Expect<Equal<MyParameters<typeof bar>, [boolean, { a: "A" }]>>,
Expect<Equal<MyParameters<typeof baz>, []>>
];
// ============= Your Code Here =============
type MyParameters<T extends (...args: any[]) => any> = T extends (
...args: infer P
) => void
? P
: void;
中等题
2.Get Return Type
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<string, MyReturnType<() => string>>>,
Expect<Equal<123, MyReturnType<() => 123>>>,
Expect<Equal<ComplexObject, MyReturnType<() => ComplexObject>>>,
Expect<Equal<Promise<boolean>, MyReturnType<() => Promise<boolean>>>>,
Expect<Equal<() => "foo", MyReturnType<() => () => "foo">>>,
Expect<Equal<1 | 2, MyReturnType<typeof fn>>>,
Expect<Equal<1 | 2, MyReturnType<typeof fn1>>>
];
type ComplexObject = {
a: [12, "foo"];
bar: "hello";
prev(): number;
};
const fn = (v: boolean) => (v ? 1 : 2);
const fn1 = (v: boolean, w: any) => (v ? 1 : 2);
// ============= Your Code Here =============
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
3. Omit
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<Expected1, MyOmit<Todo, "description">>>,
Expect<Equal<Expected2, MyOmit<Todo, "description" | "completed">>>
];
// @ts-expect-error
type error = MyOmit<Todo, "description" | "invalid">;
interface Todo {
title: string;
description: string;
completed: boolean;
}
interface Expected1 {
title: string;
completed: boolean;
}
interface Expected2 {
title: string;
}
// ============= Your Code Here =============
type MyOmit<T, K extends keyof T> = {
[key in keyof T as key extends K ? never : key]: T[key];
};
8. Readonly2
// ============= Test Cases =============
import type { Alike, Expect } from "./test-utils";
type cases = [
Expect<Alike<MyReadonly2<Todo1>, Readonly<Todo1>>>,
Expect<Alike<MyReadonly2<Todo1, "title" | "description">, Expected>>,
Expect<Alike<MyReadonly2<Todo2, "title" | "description">, Expected>>,
Expect<Alike<MyReadonly2<Todo2, "description">, Expected>>
];
// @ts-expect-error
type error = MyReadonly2<Todo1, "title" | "invalid">;
interface Todo1 {
title: string;
description?: string;
completed: boolean;
}
interface Todo2 {
readonly title: string;
description?: string;
completed: boolean;
}
interface Expected {
readonly title: string;
readonly description?: string;
completed: boolean;
}
// ============= Your Code Here =============
type MyReadonly2<T, K extends keyof T = keyof T> = {
[key in keyof T as key extends K ? never : key]: T[key];
} & {
readonly [key in K]: T[key];
};
9. Deep Readonly
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<DeepReadonly<X1>, Expected1>>,
Expect<Equal<DeepReadonly<X2>, Expected2>>
];
type X1 = {
a: () => 22;
b: string;
c: {
d: boolean;
e: {
g: {
h: {
i: true;
j: "string";
};
k: "hello";
};
l: [
"hi",
{
m: ["hey"];
}
];
};
};
};
type X2 = { a: string } | { b: number };
type Expected1 = {
readonly a: () => 22;
readonly b: string;
readonly c: {
readonly d: boolean;
readonly e: {
readonly g: {
readonly h: {
readonly i: true;
readonly j: "string";
};
readonly k: "hello";
};
readonly l: readonly [
"hi",
{
readonly m: readonly ["hey"];
}
];
};
};
};
type Expected2 = { readonly a: string } | { readonly b: number };
// ============= Your Code Here =============
type DeepReadonly<T> = T extends Function
? T
: T extends object
? { readonly [key in keyof T]: DeepReadonly<T[key]> }
: T;
10. Tuple to Union
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<TupleToUnion<[123, "456", true]>, 123 | "456" | true>>,
Expect<Equal<TupleToUnion<[123]>, 123>>
];
// ============= Your Code Here =============
type TupleToUnion<T> = T extends (infer U)[] ? U : never;
12. Chainable Options
// ============= Test Cases =============
import type { Alike, Expect } from "./test-utils";
declare const a: Chainable;
const result1 = a
.option("foo", 123)
.option("bar", { value: "Hello World" })
.option("name", "type-challenges")
.get();
const result2 = a
.option("name", "another name")
// @ts-expect-error
.option("name", "last name")
.get();
const result3 = a
.option("name", "another name")
// @ts-expect-error
.option("name", 123)
.get();
type cases = [
Expect<Alike<typeof result1, Expected1>>,
Expect<Alike<typeof result2, Expected2>>,
Expect<Alike<typeof result3, Expected3>>
];
type Expected1 = {
foo: number;
bar: {
value: string;
};
name: string;
};
type Expected2 = {
name: string;
};
type Expected3 = {
name: number;
};
// ============= Your Code Here =============
type Chainable<T = {}> = {
option<K extends string, V>(
key: K extends keyof T ? never : K,
value: V
): Chainable<Omit<T, K> & { [Key in K]: V }>;
get(): T;
};
15. Last of Array
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
type cases = [
Expect<Equal<Last<[2]>, 2>>,
Expect<Equal<Last<[3, 2, 1]>, 1>>,
Expect<Equal<Last<[() => 123, { a: string }]>, { a: string }>>
];
// ============= Your Code Here =============
type Last<T extends any[]> = T extends [...infer P, infer U] ? U : never;