00898-easy-includes

Back

type MyEqual<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false
type Includes<T extends readonly any[], U> = T extends [] ? false :
  MyEqual<T[0], U> extends true
  ? true
  : T extends [infer f, ...infer rest]
  ? Includes<rest, U>
  : false;

Solution by watanaki #35195

type IsEquar<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
type Includes<T extends readonly any[], U> = T extends [infer F, ...infer Rest]
  ? IsEquar<F, U> extends true
    ? true
    : Includes<Rest, U>
  : false;

Solution by wendao-liu #35085

My answer is inspired by util implementation of Equal but more understandable i think. It passes all given tests

type MyEquals<T,U> = 
  Readonly<T> extends T ? Readonly<U> extends T ? true : false : false;
  
type Includes<T extends readonly any[], U> = 
  T extends readonly [infer HEAD, ...infer TAIL] ? 
  Equal<HEAD,U> extends true ? true : Includes<TAIL, U> : 
    false;

Solution by CrimsoonXIII #35047

type Includes<T extends readonly unknown[], P> = P extends T[number] ? true : false

Solution by ClarityOfMind #34994

type Includes<T extends readonly any[], U> = T extends [infer First, ...infer Rest] ? (First extends U ? (U extends First ? true : false) : Includes<Rest, U>) : false;

Solution by raeyoung-kim #34957

type TupleToUnion<T extends readonly any[]> = T extends [infer First, ...infer Rest] ? First | TupleToUnion<Rest> : never;
type Includes<T extends any[], K> = K extends TupleToUnion<T> ? true : false;

We could make a TupleToUnion.

Solution by DearICE #34907

type Includes<T extends readonly any[], U> =
  Equal<U, T[0]> extends true 
  ? true
  : (T extends [any, ...infer R] 
    ? (R extends [] // if R is an empty array, the search should be terminated 
      ? false 
      : Includes<R, U>) 
    : false)

Solution by floatDreamWithSong #34871

type Includes<T extends readonly any[], K> = K extends T[number] ? true : false

Solution by weitongtong #34847

type TupleIndexes<T extends readonly any[]> = { [K in keyof T]: K }[number] ่Žทๅ–ๅ…ƒ็ป„T็š„ๆ‰€ๆœ‰็ดขๅผ• type AllEqual<T extends readonly any[], U, P extends number> = P extends P ? Equal<T[P], U> : never ๅˆฉ็”จDistributive Conditional Type๏ผŒๅฆ‚ๆžœTไธญๆ‰€ๆœ‰ๅ…ƒ็ด ้ƒฝๅ’ŒUไธ็›ธ็ญ‰ๅˆ™ไธบfalseใ€‚่‹ฅTๆฐๆœ‰ไธ€ไธชๅ…ƒ็ด ๅ’ŒU็›ธ็ญ‰ๅˆ™ไธบtrue๏ผŒ่‹ฅTๅซๆœ‰ๅ…ƒ็ด ๅ’ŒU็›ธ็ญ‰ๅˆ™ไธบbooleanใ€‚ type Includes<T extends readonly any[], U> = AllEqual<T, U, TupleIndexes<T>> extends false ? false : true

Solution by 2083335157 #34838

// @reference https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
type IsEqual<X, Y> = 
  (<T>() => T extends X ? 1 : 2) extends 
  (<T>() => T extends Y ? 1 : 2) 
    ? true
    : false;

type Includes<T extends readonly any[], U> = T extends [infer First, ...infer Rest] 
  ? IsEqual<First, U> extends true 
    ? true 
    : Includes<Rest, U> 
  : false;

Solution by eunsukimme #34815

// ไฝ ็š„็ญ”ๆกˆ
type Includes<T extends readonly any[], U> = {
  [key in keyof T]: Equal<T[key], U> extends true ? true: never;
}[number] extends never ? false : true
// ๅ€ŸๅŠฉ never ็ฉบ้›†

Solution by Atlas-lili #34729

// your answers
type Includes<T extends readonly any[], U> = T extends [infer P, ...infer R]
  ? Equal<P, U> extends true
    ? true
    : Includes<R, U>
  : false;

Solution by zeyuanHong0 #34719

type Includes<T extends readonly any[], U> = T extends [infer I, ...infer E] ? Equal<I, U> extends true ? true : Includes<E, U> : false

Solution by nathan2slime #34662

type Includes<T extends readonly unknown[], U> =
  T extends [infer First, ...infer Rest]
    ? Equal<First, U> extends true ? true : Includes<Rest, U>
    : false;

Solution by devshinthant #34548

type Includes<T extends readonly any[], U> = 
T extends [infer Head, ... infer Tail] ? 
Equal<Head, U> extends true ? true : Includes<Tail, U>
: false

Solution by binhdv155127 #34470

// ์—ฌ๊ธฐ ํ’€์ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”
type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;

type Includes<T extends readonly any[], U> = T extends [infer F, ...infer Rest]
  ? Equal<F, U> extends true
    ? true
    : Includes<Rest, U>
  : false;

Solution by LeeKangHyun #34463

type Equal<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;
type Includes<T extends readonly any[], U> = T extends [infer F, ...infer R] ? Equal<F, U> extends true ? true : Includes<R, U> : false

Solution by ktim816 #34427

type Includes<T extends readonly any[], U> = 
  T extends [infer F, ...infer R] 
    ? Equal<F, U> extends true
      ? true 
      : Includes<R, U> 
    : false;

Solution by bkdragon0228 #34377

type Includes<T extends readonly any[], U> = T extends [infer Fisrt, ...infer Reset]
  ? Equal<Fisrt, U> extends true ? true : Includes<Reset, U>
  : false

Solution by rookie-luochao #34363

export type IsEqual<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false

type Includes<T extends readonly any[], U> = T extends [infer A,...infer Reset] ? IsEqual <U,A> extends true ?true:Includes<Reset,U> : false

Solution by FrankWangMing #34340

type Eq<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false

type Includes<T extends readonly any[], U> = 
  T extends [infer Head, ...infer Tail]
    ? Eq<U, Head> extends true 
      ? true
      : Includes<Tail, U>
    : false

Solution by souzaramon #34335

๋ฌธ์ œ ์„ค๋ช…

JavaScript์˜ Array.includes ํ•จ์ˆ˜๋ฅผ ํƒ€์ž… ์‹œ์Šคํ…œ์—์„œ ๊ตฌํ˜„ํ•˜์„ธ์š”. ํƒ€์ž…์€ ๋‘ ์ธ์ˆ˜๋ฅผ ๋ฐ›๊ณ , true ๋˜๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

type isPillarMen = Includes<["Kars", "Esidisi", "Wamuu", "Santana"], "Dio">; // expected to be `false`

ํ’€์ด

๋ณด์ž๋งˆ์ž ์‹œ๋„ํ•œ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

type Includes<T extends readonly any[], U> = U extends T[number] ? true : false;

ํ•˜์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

Includes<[{}], { a: "A" }>; // true...?

ํ•ด๋‹น ํƒ€์ž…์ด true ๊ฐ€ ๋‚˜์˜ค๋Š”๊ฒƒ์ด ์ด์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” {} ํƒ€์ž…์€ "๋นˆ ๊ฐ์ฒด ํƒ€์ž…"์œผ๋กœ, ๋ชจ๋“  ๊ฐ์ฒด ํƒ€์ž…์˜ ์ƒ์œ„ ํƒ€์ž…(supertype)์œผ๋กœ ๊ฐ„์ฃผ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

{} ํƒ€์ž…์˜ ์˜๋ฏธ

TypeScript์—์„œ {} ํƒ€์ž…์€ **"๋นˆ ๊ฐ์ฒด ํƒ€์ž…"**์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•˜์ง€๋งŒ, ๊ทธ ๊ฐ์ฒด์— ์–ด๋–ค ํŠน์ •ํ•œ ์†์„ฑ์ด ์žˆ์Œ์„ ๋ช…์‹œํ•˜์ง€ ์•Š์€ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

{} ํƒ€์ž…์€ ์‚ฌ์‹ค์ƒ ๋ชจ๋“  JavaScript ๊ฐ’๊ณผ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ˆซ์ž, ๋ฌธ์ž์—ด, ๋ฐฐ์—ด, ํ•จ์ˆ˜, ๊ฐ์ฒด, null, undefined๋ฅผ ํฌํ•จํ•œ ๋ชจ๋“  ๊ฐ’์ด {} ํƒ€์ž…์— ํ• ๋‹น๋  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

let emptyObject: {} = {}; // ๋นˆ ๊ฐ์ฒด ํ• ๋‹น ๊ฐ€๋Šฅ
let numberValue: {} = 123; // ์ˆซ์ž ํ• ๋‹น ๊ฐ€๋Šฅ
let stringValue: {} = "Hello"; // ๋ฌธ์ž์—ด ํ• ๋‹น ๊ฐ€๋Šฅ
let arrayValue: {} = [1, 2, 3]; // ๋ฐฐ์—ด ํ• ๋‹น ๊ฐ€๋Šฅ
let functionValue: {} = () => {}; // ํ•จ์ˆ˜ ํ• ๋‹น ๊ฐ€๋Šฅ

// ๋” ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด ํƒ€์ž…์—๋„ ํ• ๋‹น ๊ฐ€๋Šฅ
let specificObject: {} = { a: "hello", b: 42 };

object ํƒ€์ž…์€ ์›์‹œ ๊ฐ’(primitive types)์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ, {} ํƒ€์ž…์€ ์›์‹œ ๊ฐ’๋„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, number๋‚˜ string๋„ {} ํƒ€์ž…์— ํ• ๋‹น๋  ์ˆ˜ ์žˆ์ง€๋งŒ, object ํƒ€์ž…์—๋Š” ํ• ๋‹น๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ {} ๋‚ด๋ถ€์—์„œ๋„ ํ™•์ธํ•˜์—ฌ ์™„๋ฒฝํžˆ ํ˜ธํ™˜ํ•˜๋Š”์ง€ ํ™•์ธํ•  ํ•„์š”๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ œ๊ท€์  ํ’€์ด

๊ทธ๋ ‡๋‹ค๋ฉด ์ œ๊ท€์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์ด๋Ÿฐ๊ฑด ์–ด๋–จ๊นŒ์š”? ์ €ํฌ๊ฐ€ DeepReadonly ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ œ๊ท€์ ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋˜๊ฒƒ์ฒ˜๋Ÿผ (์ €์˜ readonly์— ํ’€์ด๊ฐ€ ์ ํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค.) ์ด๋ฒˆ์—๋„ ์ œ๊ท€์ ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

type Includes<Value extends any[], Item> = Value extends [
	infer First,
	...infer Rest
]
	? Equal<First, Item> extends true // Equal์„ ์‚ฌ์šฉํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค! ๋‹น์—ฐํžˆ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋˜๊ฒ ์ง€๋งŒ ๋ง์ด์ฃ .
		? true
		: Includes<Rest, Item>
	: false;

/* _____________ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค _____________ */
import type { Equal, Expect } from "@type-challenges/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>>
];

๋ฌธ์ œ์—†์ด ๋ชจ๋‘ ์ž˜ ๋ฐ˜ํ™˜ํ•˜๋Š”๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ Equal์„ ๋Œ€์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๋ฉด ๋˜๊ฒ ๊ตฐ์š”. ์•ˆํƒ€๊น๊ฒŒ๋„ Equal์„ ๋Œ€์‹ ํ•˜๋Š” ์ œ๋„ค๋ฆญ์€ ์—†์œผ๋‹ˆ ์ง์ ‘ ๊ตฌํ˜„์„ ํ†ตํ•ด ๋งŒ๋“ค์–ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

/**
Returns a boolean for whether given two types are equal.
@link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
*/
type IsEqual<T, U> = (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U
	? 1
	: 2
	? true
	: false;

๋‹ค์Œ๊ณผ ๊ฐ™์ด ts issues์— ํฌํ•จ๋˜์–ด ์žˆ๋Š” IsEqual์„ ์‚ฌ์šฉํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

Solution

/* _____________ ์—ฌ๊ธฐ์— ์ฝ”๋“œ ์ž…๋ ฅ _____________ */

type IsEqual<T, U> = (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U
	? 1
	: 2
	? true
	: false;

type Includes<Value extends any[], Item> = Value extends [
	infer First,
	...infer Rest
]
	? IsEqual<First, Item> extends true
		? true
		: Includes<Rest, Item>
	: false;

/* _____________ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค _____________ */
import type { Equal, Expect } from "@type-challenges/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>>
];

Solution by adultlee #34121

type Includes<T extends readonly any[], U> = T extends [infer P, ...infer rest] ? Equal<P, U> extends true ? true : Includes<rest, U> : false

Solution by ouzexi #33971

type Includes<T extends readonly any[], U> = T extends [infer First, ...infer Rest] 
  ? Equal<U, First> extends true
    ? true
    : Includes<Rest, U>
  : false

Solution by notsecret32 #33863

type Includes<T extends readonly any[], U> =  T extends [infer L, ...infer R] 
  ? Equal<L, U> extends true
    ? true
    : Includes<R, U>
  : false

Solution by veralex #33756

type Equal<A, B> = (<T>() => T extends A ? 1 : 0) extends (<T>() => T extends B ? 1 : 0) ? true : false

type Includes<T extends readonly any[], U> = T extends [infer A, ...infer Rest]
  ? Equal<A, U> extends true
    ? true
    : Includes<Rest, U>
  : false

Solution by laplace1009 #33707

type Includes<T extends readonly any[], U> = 
  T extends [infer Head , ...infer Tail]
    ? Equal<Head, U> extends true
      ? true
      : Includes<Tail, U>
    : false;

้›ฃใ—ใ™ใŽใ‚‹... Head, TailใŒใ“ใ“ใงๅ‡บใฆใใ‚‹ใจใฏๆ€ใ‚ใชใ‹ใฃใŸใ€‚ Equalไฝฟใ†ใฎใฏๆƒณๅƒใงใใชใ‹ใฃใŸ

Solution by okabe-yuya #33687

// ไฝ ็š„็ญ”ๆกˆ
type Includes<T extends unknown[], K> = K extends keyof T[number] ? true : false;

Solution by SZGG2333 #33602

type Includes<P extends readonly any[], U> = true extends {
      [K in keyof P]: (<T>() => T extends U ? 1 : 2) extends <T>() => T extends P[K] ? 1 : 2 
        ? true 
        : false;
    }[number] 
  ? true : false;

Solution by Alex-Nicalace #33406

// ์—ฌ๊ธฐ ํ’€์ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”
type Includes<T extends readonly any[], U> = T extends [infer F, ...infer Rest]
  ? Equal<F, U> extends true
    ? true
    : Includes<Rest, U>
  : false;

Solution by awesomelon #33368