Giter Club home page Giter Club logo

type-challenges's Introduction

Collection of TypeScript type challenges


English | 简体中文 | 日本語 | 한국어 | Português

Intro

by the power of TypeScript's well-known Turing Completed type system

High-quality types can help improve projects' maintainability while avoiding potential bugs.

There are a bunch of awesome type utility libraries that may boost your works on types, like ts-toolbelt, utility-types, SimplyTyped, etc., which you can already use.

This project is aimed at helping you better understand how the type system works, writing your own utilities, or just having fun with the challenges. We are also trying to form a community where you can ask questions and get answers you have faced in the real world - they may become part of the challenges!

Challenges

Click the following badges to see details of the challenges.

Note: Challenges work in the strict mode.


1
13・Hello World

13
4・Pick 7・Readonly 11・Tuple to Object 14・First of Array 18・Length of Tuple 43・Exclude 189・Awaited 268・If 533・Concat 898・Includes 3057・Push 3060・Unshift 3312・Parameters

97
2・Get Return Type 3・Omit 8・Readonly 2 9・Deep Readonly 10・Tuple to Union 12・Chainable Options 15・Last of Array 16・Pop 20・Promise.all 62・Type Lookup 106・Trim Left 108・Trim 110・Capitalize 116・Replace 119・ReplaceAll 191・Append Argument 296・Permutation 298・Length of String 459・Flatten 527・Append to object 529・Absolute 531・String to Union 599・Merge 612・KebabCase 645・Diff 949・AnyOf 1042・IsNever 1097・IsUnion 1130・ReplaceKeys 1367・Remove Index Signature 1978・Percentage Parser 2070・Drop Char 2257・MinusOne 2595・PickByType 2688・StartsWith 2693・EndsWith 2757・PartialByKeys 2759・RequiredByKeys 2793・Mutable 2852・OmitByType 2946・ObjectEntries 3062・Shift 3188・Tuple to Nested Object 3192・Reverse 3196・Flip Arguments 3243・FlattenDepth 3326・BEM style string 3376・InorderTraversal 4179・Flip 4182・Fibonacci Sequence 4260・AllCombinations 4425・Greater Than 4471・Zip 4484・IsTuple 4499・Chunk 4518・Fill 4803・Trim Right 5117・Without 5140・Trunc 5153・IndexOf 5310・Join 5317・LastIndexOf 5360・Unique 5821・MapTypes 7544・Construct Tuple 8640・Number Range 8767・Combination 8987・Subsequence 9142・CheckRepeatedChars 9286・FirstUniqueCharIndex 9616・Parse URL Params 9896・GetMiddleElement 9898・Appear only once 9989・Count Element Number To Object 10969・Integer 16259・ToPrimitive 17973・DeepMutable 18142・All 18220・Filter 21104・FindAll 21106・Combination key type 21220・Permutations of Tuple 25170・Replace First 25270・Transpose 26401・JSON Schema to TypeScript 27133・Square 27152・Triangular number 27862・CartesianProduct 27932・MergeAll 27958・CheckRepeatedTuple 28333・Public Type 29650・ExtractToObject 29785・Deep Omit 30301・IsOdd 30430・Tower of hanoi 30958・Pascal's triangle 30970・IsFixedStringLiteralType

49
6・Simple Vue 17・Currying 1 55・Union to Intersection 57・Get Required 59・Get Optional 89・Required Keys 90・Optional Keys 112・Capitalize Words 114・CamelCase 147・C-printf Parser 213・Vue Basic Props 223・IsAny 270・Typed Get 300・String to Number 399・Tuple Filter 472・Tuple to Enum Object 545・printf 553・Deep object to unique 651・Length of String 2 730・Union to Tuple 847・String Join 956・DeepPick 1290・Pinia 1383・Camelize 2059・Drop String 2822・Split 2828・ClassPublicKeys 2857・IsRequiredKey 2949・ObjectFromEntries 4037・IsPalindrome 5181・Mutable Keys 5423・Intersection 6141・Binary to Decimal 7258・Object Key Paths 8804・Two Sum 9155・ValidDate 9160・Assign 9384・Maximum 9775・Capitalize Nest Object Keys 13580・Replace Union 14080・FizzBuzz 14188・Run-length encoding 15260・Tree path array 19458・SnakeCase 25747・IsNegativeNumber 28143・OptionalUndefined 30575・BitwiseXOR 32427・Unbox 32532・Binary Addition

15
5・Get Readonly Keys 151・Query String Parser 216・Slice 274・Integers Comparator 462・Currying 2 476・Sum 517・Multiply 697・Tag 734・Inclusive Range 741・Sort 869・DistributeUnions 925・Assert Array Index 6228・JSON Parser 7561・Subtract 31447・CountReversePairs

By Tags
#JSON26401・JSON Schema to TypeScript
#application12・Chainable Options 8767・Combination 6・Simple Vue 213・Vue Basic Props
#arguments191・Append Argument 3196・Flip Arguments
#array14・First of Array 533・Concat 898・Includes 3057・Push 3060・Unshift 15・Last of Array 16・Pop 20・Promise.all 459・Flatten 949・AnyOf 3062・Shift 3243・FlattenDepth 4425・Greater Than 5117・Without 5153・IndexOf 5310・Join 5317・LastIndexOf 5360・Unique 8767・Combination 18142・All 18220・Filter 25270・Transpose 27133・Square 27152・Triangular number 27932・MergeAll 30430・Tower of hanoi 30958・Pascal's triangle 17・Currying 1 2822・Split 5423・Intersection 8804・Two Sum 9160・Assign 9384・Maximum 9775・Capitalize Nest Object Keys 14080・FizzBuzz 32427・Unbox 32532・Binary Addition 216・Slice 734・Inclusive Range 741・Sort 925・Assert Array Index
#built-in4・Pick 7・Readonly 43・Exclude 189・Awaited 3312・Parameters 2・Get Return Type 3・Omit
#conditional type21220・Permutations of Tuple
#deep9・Deep Readonly 17973・DeepMutable 553・Deep object to unique 956・DeepPick
#filter18220・Filter
#function32427・Unbox
#infer3312・Parameters 2・Get Return Type 10・Tuple to Union 2070・Drop Char 4260・AllCombinations 9616・Parse URL Params 55・Union to Intersection 57・Get Required 59・Get Optional 399・Tuple Filter 730・Union to Tuple 2059・Drop String 14080・FizzBuzz 734・Inclusive Range 741・Sort
#json6228・JSON Parser
#map62・Type Lookup 5821・MapTypes
#math529・Absolute 2257・MinusOne 25270・Transpose 27133・Square 27152・Triangular number 30958・Pascal's triangle 6141・Binary to Decimal 8804・Two Sum 14080・FizzBuzz 274・Integers Comparator 476・Sum 517・Multiply
#number25747・IsNegativeNumber
#object599・Merge 645・Diff 2595・PickByType 2757・PartialByKeys 2759・RequiredByKeys 2852・OmitByType 2946・ObjectEntries 3188・Tuple to Nested Object 3376・InorderTraversal 4179・Flip 5821・MapTypes 27932・MergeAll 29650・ExtractToObject 2949・ObjectFromEntries 9160・Assign 9775・Capitalize Nest Object Keys
#object-keys7・Readonly 11・Tuple to Object 8・Readonly 2 9・Deep Readonly 527・Append to object 1130・ReplaceKeys 1367・Remove Index Signature 2793・Mutable 28333・Public Type 7258・Object Key Paths 5・Get Readonly Keys
#omit object-keys deep29785・Deep Omit
#promise189・Awaited 20・Promise.all 32427・Unbox
#readonly7・Readonly 8・Readonly 2 9・Deep Readonly 2793・Mutable 17973・DeepMutable
#recursion21220・Permutations of Tuple 1383・Camelize 32532・Binary Addition
#split2822・Split
#string531・String to Union 8767・Combination 9142・CheckRepeatedChars 9286・FirstUniqueCharIndex 9616・Parse URL Params 21104・FindAll 30301・IsOdd 2822・Split 4037・IsPalindrome 19458・SnakeCase
#template literal25747・IsNegativeNumber
#template-literal106・Trim Left 108・Trim 110・Capitalize 116・Replace 119・ReplaceAll 298・Length of String 529・Absolute 612・KebabCase 1978・Percentage Parser 2070・Drop Char 2688・StartsWith 2693・EndsWith 3326・BEM style string 4260・AllCombinations 4803・Trim Right 5140・Trunc 9616・Parse URL Params 10969・Integer 21104・FindAll 112・Capitalize Words 114・CamelCase 147・C-printf Parser 270・Typed Get 300・String to Number 472・Tuple to Enum Object 545・printf 651・Length of String 2 2059・Drop String 19458・SnakeCase 151・Query String Parser 274・Integers Comparator 476・Sum 517・Multiply 6228・JSON Parser
#this6・Simple Vue 1290・Pinia
#tuple18・Length of Tuple 3312・Parameters 10・Tuple to Union 3188・Tuple to Nested Object 3192・Reverse 3326・BEM style string 4471・Zip 4484・IsTuple 4499・Chunk 4518・Fill 7544・Construct Tuple 21220・Permutations of Tuple 27133・Square 27152・Triangular number 399・Tuple Filter 472・Tuple to Enum Object 730・Union to Tuple 2822・Split 32427・Unbox 7561・Subtract
#union4・Pick 43・Exclude 3・Omit 10・Tuple to Union 62・Type Lookup 296・Permutation 531・String to Union 1042・IsNever 1097・IsUnion 3326・BEM style string 4260・AllCombinations 5117・Without 8987・Subsequence 9142・CheckRepeatedChars 21220・Permutations of Tuple 27862・CartesianProduct 27932・MergeAll 730・Union to Tuple 1383・Camelize 5423・Intersection
#utils268・If 1042・IsNever 5821・MapTypes 55・Union to Intersection 57・Get Required 59・Get Optional 89・Required Keys 90・Optional Keys 223・IsAny 270・Typed Get 2828・ClassPublicKeys 2857・IsRequiredKey 5181・Mutable Keys 32427・Unbox 5・Get Readonly Keys
#vue6・Simple Vue 213・Vue Basic Props 1290・Pinia
          

By Plain Text

warm-up (1)

easy (13)

medium (97)

hard (49)

extreme (15)


Upcoming challenges

🔥 Start the challenge in TypeScript Playground

🚀 Start the challenge locally in your IDE or text editor with TypeScript language support

⚡️ Start the challenge in VS Code Extension

Recommended Readings

Official

Articles

Talks

Projects / Solutions

Books

How to Contribute

There are several ways you can contribute to this project

  • Share your answers / solutions
  • Propose new challenges
  • Add more test cases to the existing challenges
  • Provide learning resources or ideas of how to solve challenges
  • Share the problems you have faced in real-world projects, regardless you having the solution or not - the community would help you as well
  • Help with others by discussion in issues
  • Contribute the infra of this project TODOs.md

Just open an issue and choose the corresponding template. Thanks!

Play Locally

You can build the challenges and play locally using your preferred IDE or text editor with TypeScript language support.

To do that, you will need the latest version of Node.js and pnpm installed.

After cloning the repo, installed the dependencies by:

pnpm install

Then and run the generate script:

pnpm generate

It will prompt you to select the desired language, then you can find the generated challenges in the ./playground folder.

Later if you want to update playground while keeping your changes:

pnpm generate --keep-changes

OR

pnpm generate -K

Thanks

This project was born from solving real-world types problem with @hardfist and @MeCKodo. And great thanks to @sinoon who contributed a lot while giving early feedback on this project.

Inspired by

Contributors

License

MIT

type-challenges's People

Contributors

alexsey avatar antfu avatar bre30kra69cs avatar ch3cknull avatar cutefcc avatar dogdriip avatar dqn avatar g-plane avatar github-actions[bot] avatar jazelly avatar jiangshanmeta avatar jiatln avatar jonghwanwon avatar kawamataryo avatar kynefuk avatar leelejia avatar likui628 avatar majorlift avatar mistlog avatar namewjp avatar sinoon avatar suica avatar talljack avatar tenkirin avatar tisou1 avatar uid11 avatar xianshenglu avatar xjq7 avatar yash-singh1 avatar yrming avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

type-challenges's Issues

3 - Omit<T, K>

type MyOmit<T, K> = {
  [k in Exclude<keyof T, K>]: T[k]
}

Array/Tuple to Union

💡 Question Request

Feel free to raise a question that you have faced in your projects,
please clearly describe it so people can better help you with it.

If we found it's solvable and good to be in our collection,
we will properly credit you as the original question provider.

An ArrayToUnions<T> generic coverting array/tuple to its values' union

const arr = ['foo', 'bar'] as const

type union = ArrayToUnion<typeof arr> // expect to be 'foo' | 'bar'

43 - Exclude

type MyExclude<T, U> =  T extends U ? never : T;

7 - Readonly<T>

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

type MyReadonly<T> = { readonly [K in keyof T]: T[K] }

14 - First of Array

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

4 - Pick<T, K>

type MyPick<T, K extends keyof T> = {
  [k in K]: T[k]
}

18 - Length of Tuple

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
12 - my one-line solution

type Length<T extends {readonly [x: number]: any; readonly length: number;}> = T['length'] 

5 - Get Readonly Keys

type GetReadonlyKeys<T> = Exclude<{
  [K in keyof T]: Equal<{ [k in K]: T[K] }, { -readonly [k in K]: T[K] }> extends true ? never : K
}[keyof T], undefined>;

16 - Pop

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

This solution requires TypeScript 4.0

type Pop<T extends any[]> = T extends [...infer P, any] ? P : never

Exclude

Info

difficulty: easy
title: Exclude
#tags: built-in

Question

Implement the built-in Exclude<T, U>

Exclude from T those types that are assignable to U

Template

type MyExclude<T, U> = any

Test Cases

import { Equal, Expect, ExpectFalse, NotEqual } from '@type-challenges/utils'

type cases = [
    Expect<Equal<MyExclude<"a" | "b" | "c", "a">, Exclude<"a" | "b" | "c", "a">>>,
    Expect<Equal<MyExclude<"a" | "b" | "c", "a" | "b">, Exclude<"a" | "b" | "c", "a" | "b">>>,
    Expect<Equal<MyExclude<string | number | (() => void), Function>, Exclude<string | number | (() => void), Function>>>,
]

3 - Omit<T, K>

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

To get into this, you need to understand the Pick(#3) challenge first. The difference between it is that MyExclude is introduced. You can use the built-in Exclude to achieve that, however, a self-implemented one is included in the solution.

// TODO: explain what happened in MyExclude

type MyExclude<A, B> = A extends B ? never : A;

type MyOmit<T, K extends keyof T> = { [S in MyExclude<keyof T, K>]: T[S] }

10 - Tuple to Union

✍️ Answers

#10 - Tuples are JUST Arrays

For example:
#12 - my one-line solution

type TupleToUnion<T> = T extends any[] ? T[number] : never;

6 - Simple Vue

declare function SimpleVue<D, C, M>(options: {
  data: () => D,
  computed: C,
  methods: M,
  // methods: { [k in keyof M]: (this: ThisType<D & C & M>) => M[k] },
} & ThisType<D & { [k in keyof C]: C[k] extends (...args: any[]) => any ? ReturnType<C[k]> : never } & M>): any

17 - Currying 1

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
12 - my one-line solution

type Unshift<T> = T extends [infer K, ...infer U] ? U : unknown
type Head<T> = T extends [infer K, ...infer U] ? K : unknown

type Curried<T, R> = T extends Array<any>
  ? T['length'] extends 1
    ? (args: Head<T>) => R
    : (args: Head<T>) => Curried<Unshift<T>, R>
  : never

declare function Currying<T extends unknown[], R>(fn: (...args: T) => R): Curried<T, R>

5 - Get Readonly Keys

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

Solution in piotrwitek/utility-types

/**
 * ReadonlyKeys
 * @desc Get union type of keys that are readonly in object type `T`
 * Credit: Matt McCutchen
 * https://stackoverflow.com/questions/52443276/how-to-exclude-getter-only-properties-from-type-in-typescript
 * @example
 *   type Props = { readonly foo: string; bar: number };
 *
 *   // Expect: "foo"
 *   type Keys = ReadonlyKeys<Props>;
 */
export type ReadonlyKeys<T extends object> = {
  [P in keyof T]-?: IfEquals<
    { [Q in P]: T[P] },
    { -readonly [Q in P]: T[P] },
    never,
    P
  >
}[keyof T]

type IfEquals<X, Y, A = X, B = never> = 
  (<T>() => T extends X ? 1 : 2) extends 
  (<T>() => T extends Y ? 1 : 2) ? A : B

Solution provided by @browsnet

type GetReadonlyKeys<T extends Object> = {
  [K in keyof T]: 
    (<S>() => S extends { [Z in K]: T[Z] } ? 2 : 1) extends 
    (<S>() => S extends { -readonly [Z in K]: T[Z] } ? 2: 1) ? never : K
}[keyof T]

Extend Reading

6 - Simple Vue

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

type GetComputed<C> = C extends Record<string, (...args: any[]) => any> 
  ? { [S in keyof C]: ReturnType<C[S]> } 
  : never

declare function SimpleVue<D, C, M>(
  options: {
    data: () => D,
    computed: C,
    methods: M,
  } & ThisType<D & M & GetComputed<C>>
): any

Extend Readings

Updates

The challenges get updated with stricter rules in #173, check out #172 for a more proper answer.

Promise.all

Info

difficulty: medium # medium / hard / extreme
title: Promise.all
tags: array, built-in 

Question

Type the function PromiseAll that accepts an array of PromiseLike objects, the returning value should be Promise<T> where T is the resolved result array.

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise<string>((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

// expected to be `Promise<[number, number, string]>`
const p = Promise.all([promise1, promise2, promise3] as const)

Template

declare function PromiseAll(promises: any[]): any

Test Cases

import { Equal, Expect } from '@type-challenges/utils'

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise<string>((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

type cases = [
  Expect<Equal<PromiseAll([promise1, promise2, promise3] as const), Promise<[3, 42, string]>>>
]

17 - Currying 1

type Curried<T extends (...args: any) => any> = {
  0: T extends (...args: [infer A]) => infer R ? (arg: A) => R : never,
  1: T extends (...args: [infer A, ...infer Args]) => infer R ? (arg: A) => Curried<(...args: Args) => R> : never,
}[T extends (...args: [any]) => any ? 0 : 1]

declare function Currying<T extends (...args: any) => any>(fn: T): Curried<T>

Get Required

Info

difficulty: hard
title: Get Required
tags: utils, infer

Question

Implement the advanced util type GetRequired<T>, which remains all the required fields

For example

type I = GetRequired<{ foo: number, bar?: string }> // expected to be { foo: number }

Template

type GetRequired<T> = any

Test Cases

import { Equal, Expect, ExpectFalse, NotEqual } from '@type-challenges/utils'

type cases = [
    Expect<Equal<GetRequired<{ foo: number, bar?: string }>, { foo: number }>>,
    Expect<Equal<GetRequired<{ foo: undefined, bar?: undefined }>, { foo: undefined }>>,
]

4 - Pick

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

type MyPick<T, K extends keyof T> = { [S in K]: T[S] }

新题目 Test

请按照以下的模版填充相应的内容,一个 PR 会自动生成并保持与本 Issue 的内容同步。

你不需要提供详细的答案或教学,但请保证题目可解。

基本信息

# 题目难度
difficulty: easy # medium / hard / extreme

# 题目标题
title: 测试题3

# 题目标签
#tags: union, array # separate by comma

题目

在这里描述你的题目并给出一些例子。支持使用 Markdown。真的吗!

题目模版

以下是给予挑战者开始做题的代码模版,在大部分情况下你只需要修改类型名称使其符合你的题目与判题测试,实现的部分保持 any 即可。

type YourType = any

判题测试

请为你的题目提供一些判题测试,你可以使用 @type-challenges/utils 中提供的一些工具进行判断。

import { Equal, Expect, ExpectFalse, NotEqual } from '@type-challenges/utils'

type cases = [
  Expect<Equal<true, true>>
]

4 - Pick<T, K>

type MyPick<T, K extends keyof T> = { [S in K]: T[S] }

9 - Deep Readonly

type DeepReadonly<T> = {
  readonly [k in keyof T]: T[k] extends Record<any, any>
    ? T[k] extends Function
      ? T[k]
      : DeepReadonly<T[k]>
    : T[k]
}

Union to Intersection

Info

difficulty: hard
title: Union to Intersection
tags: utils, infer

Question

Implement the advanced util type UnionToIntersection<U>

For example

type I = Union2Intersection<'foo' | 42 | true> // expected to be 'foo' & 42 & true

Template

type UnionToIntersection<U> = any

Test Cases

import { Equal, Expect, ExpectFalse, NotEqual } from '@type-challenges/utils'

type cases = [
    Expect<Equal<UnionToIntersection<'foo' | 42 | true>, 'foo' & 42 & true>>,
    Expect<Equal<UnionToIntersection<(() => 'foo') | ((i: 42) => true)>, (() => 'foo') & ((i: 42) => true)>>,
]

16 - Pop

works on TS3.9

type Unshift<T extends any[], K> =
    ((a: K, ...args: T) => void) extends ((...args: infer U) => void)
    ? U : never;

type Reverse<T extends any[], Target extends any[] = []> = {
    0: Target;
    1: (
        ((...args: T) => void) extends ((a: infer First, ...args: infer Rest) => void)
        ? Reverse<Rest, Unshift<Target, First>> : never
    );
}[T extends [any, ...any[]] ? 1 : 0];

type Pop<T extends any[]> =
    ((...args: Reverse<T>) => void) extends ((a: any, ...args: infer K) => void)
    ? Reverse<K> : never;

5 - Get Readonly Keys

✍️ Answers

5 - my solution

type ReadonlyKeys<T, R extends { [K in keyof T]: any } = Readonly<T>> = {
    [K in keyof T]: Equal<Pick<T, K>, Pick<R, K>> extends true ? K : never
}[keyof T]

15 - Last of Array

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

12 - Chainable Options

type Chainable<T = {}> = {
  option<K extends string | number | symbol, U>(key: K , value: U): Chainable<T & { [k in K]: U }>
  get(): { [k in keyof T]: T[k] }
}

10 - Tuple to Union

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

export type TupleToUnion<T> = T extends Array<infer ITEMS> ? ITEMS : never

16 - Pop

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

14 - First of Array

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
12 - my one-line solution

type First<T extends any[]> = T extends [infer P, ...any[]] ? P : never

11 - Tuple to Object

type TupleToObject<T extends ReadonlyArray<string | number>> = {
  [k in T[number]]: k
}

12 - Chainable Options

✍️ Answers

#12 - Chainable Options

type Chainable<O = {}> = {
  option<K extends string, V>(key: K, value: V): Chainable<O & { [k in K]: V }>
  get(): O
}

3 - Omit<T, K>

type Diff<T extends string | number | symbol, U extends string | number | symbol> =
    ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];  
type MyOmit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;

Type Lookup

You need to provide a detailed description of your new challenge, either in English or Chinese are acceptable.

Detailed solution/guide is not required, but be sure the challenge is solvable.

Please follow the template and fill the info. A PR will be auto-generated and always reflect on your changes.

Info

Basic info of your challenge questions,

difficulty: medium # medium / hard / extreme
title: Type Lookup
tags: union, map

Question

Sometimes, you may want to lookup for a type in a union to by their attributes.

In this challenge, I would like to have get the couponing type by searching for the common type field in the union Cat | Dog. In other words, I will expect to get Dog for LookUp<Dog | Cat, 'dog'> and Cat for LookUp<Dog | Cat, 'cat'> in the following example.

interface Cat {
  type: 'cat'
  breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}

interface Dog {
  type: 'dog'
  breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
  color: 'brown' | 'white' | 'black'
}

const MyDog = LookUp<Cat | Dog, 'dog'> // expected to be `Dog`

Template

This is the template for challengers to start the coding. Basically, you just need to change the name of your generic/function and leave to implementation any.

type LookUp<U, T> = any

Test Cases

Provide some test cases for your challenge, you can use some utils from @type-challenges/utils for asserting.

import { Equal, Expect } from '@type-challenges/utils'

interface Cat {
  type: 'cat'
  breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}

interface Dog {
  type: 'dog'
  breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
  color: 'brown' | 'white' | 'black'
}

type Animal = Cat | Dog

type cases = [
  Expect<Equal<LookUp<Animal, 'dog'>, Dog>>,
  Expect<Equal<LookUp<Animal, 'cat'>, Cat>>,
]

12 - Chainable Options

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

type Chainable<Options = {}> = {
  option<K extends string, V>(key: K, value: V): Chainable<Options & { [S in K]: V }>
  get(): Options
}

This challenge is inspired by @types/yargs

8 - Readonly2<T, K>

✍️ Answers

Name your title starting with the question no you are trying to answer.

For example:
#12 - my one-line solution

type Diff<A, B> = A extends B ? never : A

type MyReadonly2<T, K extends keyof T = keyof T> =
  { readonly [S in K]: T[S] }
  & { [S in Diff<keyof T, K>]: T[S] }

Get Optional

Info

difficulty: hard
title: Get Optional
tags: utils, infer

Question

Implement the advanced util type GetOptional<T>, which remains all the optional fields

For example

type I = GetOptional<{ foo: number, bar?: string }> // expected to be { bar?: string }

Template

type GetOptional<T> = any

Test Cases

import { Equal, Expect, ExpectFalse, NotEqual } from '@type-challenges/utils'

type cases = [
    Expect<Equal<GetOptional<{ foo: number, bar?: string }>, { bar?: string }>>,
    Expect<Equal<GetOptional<{ foo: undefined, bar?: undefined }>, { bar?: undefined }>>,
]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.