条件类型中的类型特异性

Type specificity in conditional type

我正在尝试以一种方式键入 React 组件的属性,当其中一个属性具有特定值时,另一个属性的类型 属性 会发生变化。总的来说,如果输入类型类似于 string | number,我知道该怎么做,但如果它是 string | "specificString",我不知道该怎么做。也许这甚至不可能?

这是我实现该目标的两次尝试。

type Action = "createItem" | "updateItem" | "deleteItem";

type Props<TName = string> = {
    name: TName;
    value: TName extends "_action" ? Action : string;
};

const props: Props = {
    name: "_action",
    value: "wrongAction", // I want it to error
};

第二次尝试:

type Action = "createItem" | "updateItem" | "deleteItem";

type Props = {
    name: "_action";
    value: Action;
} | {
    name: string;
    value: string;
};

const props: Props = {
    name: "_action",
    value: "wrongAction", // I want it to error
};

Playground link

有什么实现方法吗?谢谢!

看这个例子:

import React from 'react'

type Action = "createItem" | "updateItem" | "deleteItem";

type ValidateProps<T> =
  /**
   * Check whether our argument has allowed type shape
   */
  T extends { name: infer A, value: infer V }
  /**
   * Check if [name] is "_action"
   */
  ? ('_action' extends A
    /**
     * If [name] is "_action" and [value] is Action
     */
    ? (V extends Action
      /**
       * Return T
       */
      ? T
      /**
       * Otherwise highlight wrong property
       */
      : { name: A, value: 'Error: [value] is not allowed' })
    : { name: A, value: V }
  )
  : never

type Props<Name, Value> = {
  name: Name,
  value: Value
}

const Foo = <
  Name extends string,
  Value extends string,
  >(props: ValidateProps<Props<Name, Value>>) => <div />

const allowed1 = <Foo name="_action" value="createItem" /> // ok
const allowed2 = <Foo name="anything" value="hello" /> // ok
const not_allowed = <Foo name="_action" value="hello" /> // expected error

Playground

您需要从 namevalue 属性 推断文字类型,然后他们对其进行验证。

如果你对参数类型推断感兴趣,可以查看我的文章here and here

P.S。请随意使用 never 而不是 'Error: [value] is not allowed'。为了便于阅读,我添加了它