[TypeScript] Make typescript stick - 2

If<C, T, F>

Implement a type that evaluates to T if the type C is true or F if C is false.

// Implement this type
type If<C, T, F> = C extends true ? T: F

// Tests
type cases = [
  Expect<Equal<If<true, "apple", "pear">, "apple">>,
  Expect<Equal<If<false, "orange", 42>, 42>>
]

 

LengthOfTuple<T>

Implement a type that evaluates to a numeric type literal, equivalent to the length of a specified tuple type T

type LengthOfTuple<T extends readonly any[]> = T['length']

// Tests
const Fruits = ["cherry", "banana"] as const
type cases = [
  Expect<Equal<LengthOfTuple<[1, 2, 3]>, 3>>,
  Expect<NotEqual<LengthOfTuple<[1, 2, 3]>, 2>>,
  Expect<Equal<LengthOfTuple<typeof Fruits>, 2>>,
  Expect<Equal<LengthOfTuple<[]>, 0>>
]

 

EndsWith<A, B>

Implement a type that evaluates to true if the type A ends with the type B, otherwise false.

type EndsWith<A extends string, B extends string> = A extends `${any}${B}` ? true: false;

// Tests
type cases = [
  Expect<Equal<EndsWith<"ice cream", "cream">, true>>,
  Expect<Equal<EndsWith<"ice cream", "chocolate">, false>>
]

 

Concat<A, B>

Implement a type that concatenates two tuple types A, and B

type Concat<A extends any[], B extends any[]> = [
  ...A,
  ...B
]

// Tests
type cases = [
  Expect<Equal<Concat<[], []>, []>>,
  Expect<Equal<Concat<[], ["hello"]>, ["hello"]>>,
  Expect<
    Equal<Concat<[18, 19], [20, 21]>, [18, 19, 20, 21]>
  >,
  Expect<
    Equal<
      Concat<[42, "a", "b"], [Promise<boolean>]>,
      [42, "a", "b", Promise<boolean>]
    >
  >
]

 

IsTuple<T>

Implement a type IsTuple, which takes an input type T and returns whether T is tuple type.

https://www.tutorialsteacher.com/typescript/typescript-tuple

// @errors: 2344
type Expect<T extends true> = T
type Equal<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false

type NotEqual<X, Y> = true extends Equal<X, Y> ? false : true

// ---cut---

// Implement this type
/* _____________ Your Code Here _____________ */

type IsTuple<T> = [T] extends [never] 
  ? false
  : T extends readonly any[] 
    ? any[] extends T 
      ? false
      : true
    : false;
type x = never extends any[] ? true: false
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<IsTuple<[]>, true>>,
  Expect<Equal<IsTuple<[number]>, true>>,
  Expect<Equal<IsTuple<readonly [1]>, true>>,
  Expect<Equal<IsTuple<{ length: 1 }>, false>>,
  Expect<Equal<IsTuple<number[]>, false>>,
  Expect<Equal<IsTuple<never>, false>>,
]

 

TupleToNestedObject<P, V>

Given a tuple type T that only contains string type, and a type U, build an object recursively.

// Need to make F to be string type, then you could do [K in F]
type TupleToNestedObject<P extends any[], V> = P extends [infer F extends string, ...(infer RT)] ? {
  [K in F]: TupleToNestedObject<RT, V>
}: V

// Tests

type cases = [
  Expect<
    Equal<TupleToNestedObject<["a"], string>, { a: string }>
  >,
  Expect<
    Equal<
      TupleToNestedObject<["a", "b"], number>,
      { a: { b: number } }
    >
  >,
  Expect<
    Equal<
      TupleToNestedObject<["a", "b", "c"], boolean>,
      { a: { b: { c: boolean } } }
    >
  >,
  Expect<Equal<TupleToNestedObject<[], boolean>, boolean>>
]

 

IndexOf<T, U>

Implement the type version of Array.indexOfIndexOf<T, U> takes an Array T, any U and returns the index of the first U in Array T.

// T will be reduce to []
// ACC will has all the items
type IndexOf<T extends any[], U, ACC extends any[] = []> = T[0] extends U 
  ? ACC['length']
  : T extends [infer FIRST, ...infer REST] 
    ? IndexOf<REST, U, [...ACC, FIRST]> 
      : -1

let x: IndexOf<[1, 2, 3], 2>
// Tests

type cases = [
  Expect<Equal<IndexOf<[1, 2, 3], 2>, 1>>,
  Expect<Equal<IndexOf<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>, 2>>,
  Expect<Equal<IndexOf<[0, 0, 0], 2>, -1>>
]

 

Wrap function return type into Promise

import { expectType } from "tsd";

// IMPLEMENT THIS TYPE
export type WrapForPenpal<T> = {
  [K in keyof T]: T[K] extends { (...args: infer Arga): infer RT }
    ? (...args: Arga) => RT extends Promise<any> ? RT : Promise<RT>
    : T[K];
};

/**
 * Test Scenario - Do not change anything below this line
 */
const methods = {
  add(a: number, b: number): number {
    return a + b;
  },
  doAsyncAdd(a: number, b: number): Promise<number> {
    return Promise.resolve(a + b);
  },
  subtract(a: number, b: number): number {
    return a - b;
  },
};
const asyncMethods: WrapForPenpal<typeof methods> = {} as any;

let addPromise = asyncMethods.add(1, 2);
let addPromise2 = asyncMethods.doAsyncAdd(1, 2);
expectType<Promise<number>>(addPromise);
expectType<Promise<number>>(addPromise2);
// @ts-expect-error
expectType<typeof addPromise>("this should fail");

let subtractPromise = asyncMethods.subtract(1, 2);
expectType<Promise<number>>(subtractPromise);
// @ts-expect-error
expectType<typeof subtractPromise>("this should fail");

 

posted @ 2022-07-21 15:02  Zhentiw  阅读(27)  评论(0编辑  收藏  举报