[Typescript] NoInfer

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: {},
  },
});

 

posted @   Zhentiw  阅读(91)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2022-02-23 [Whole Web] SQL INJECTION
2022-02-23 [Whole Web] CROSS SITE SCRIPTING (XSS)
2019-02-23 [Functional Programming] Pointy Functor Factory
2019-02-23 [Functional Programming] Async IO Functor
2017-02-23 [HTML5] Focus management using CSS, HTML, and JavaScript
2017-02-23 [TypeScript] Increase TypeScript's type safety with noImplicitAny
2017-02-23 [React] displayName for stateless component
点击右上角即可分享
微信分享提示