首页 > 其他分享 >[Typescript] NoInfer

[Typescript] NoInfer

时间:2023-02-23 16:13:27浏览次数:45  
标签:Typescript const initial NoInfer states makeFiniteStateMachine config

From ts-toolbelt



/**
 * Explain to TS which function parameter has priority for generic inference
 * @param A to de-prioritize
 * @returns `A`
 * @example
 * ```ts
 * import {F} from 'ts-toolbelt'
 *
 * const fn0 = <A extends any>(a0: A, a1: F.NoInfer<A>): A => {
 *  return {} as unknown as A // just for the example
 * }
 *
 * const fn1 = <A extends any>(a0: F.NoInfer<A>, a1: A): A => {
 *  return {} as unknown as A // just for the example
 * }
 *
 * const fn2 = <A extends any>(a0: F.NoInfer<A>, a1: F.NoInfer<A>): A => {
 *  return {} as unknown as A // just for the example
 * }
 *
 * const test0 = fn0('b', 'a') // error: infer priority is `a0`
 * const test1 = fn1('b', 'a') // error: infer priority is `a1`
 * const test2 = fn2('b', 'a') // works: infer priority is `a0` | `a1`
 * ```
 * @see https://stackoverflow.com/questions/56687668
 */
export type NoInfer<A extends any> =
    [A][A extends any ? 0 : never]

 

Without NoInfer:

interface FSMConfig<TState extends string> {
  initial: TState; 
  states: Record<
    TState,
    {
      onEntry?: () => void;
    }
  >;
}

export const makeFiniteStateMachine = <TState extends string>(
  config: FSMConfig<TState>
) => config;

// const makeFiniteStateMachine: <"a">(config: FSMConfig<"a">) => FSMConfig<"a">
const config = makeFiniteStateMachine({
  initial: 'a',
  states: {
    a: {
      onEntry: () => {
        console.log('a');
      },
    },
    // b should be allowed to be specified!
    b: {},
  },
});

Somehow makeFiniteStateMachine only infer `a` for TState.

 

We need to tell typescript, no not infer initial value:

import { F } from 'ts-toolbelt';

interface FSMConfig<TState extends string> {
  initial: F.NoInfer<TState>;
  states: Record<
    TState,
    {
      onEntry?: () => void;
    }
  >;
}

export const makeFiniteStateMachine = <TState extends string>(
  config: FSMConfig<TState>
) => config;

const config = makeFiniteStateMachine({
  initial: 'a',
  states: {
    a: {
      onEntry: () => {
        console.log('a');
      },
    },
    // b should be allowed to be specified!
    b: {},
  },
});

const config2 = makeFiniteStateMachine({
  // c should not be allowed! It doesn't exist on the states below
  // @ts-expect-error
  initial: 'c',
  states: {
    a: {},
    // b should be allowed to be specified!
    b: {},
  },
});

 

标签:Typescript,const,initial,NoInfer,states,makeFiniteStateMachine,config
From: https://www.cnblogs.com/Answer1215/p/17148393.html

相关文章