如何使用联合类型作为函数参数

How to use union type as function parameter

在下面的示例中,我创建了一个联合类型(字符串或数字)。然后我创建了一个函数签名,它应该接受一个字符串或数字作为输入。但是现在我不能使用这个函数定义

type AB = string | number

type X = (inp: AB) => void;

const x: X = (inp: number) => { console.log('ok')}; // <-- ERROR
const y: X  = (inp: string) => { console.log('ok')}; // <- ERROR

因为常量x和y有错误

UPDATED DEMO

类型 AB 可以更改,可以添加更多类型,所以如果我可以在定义类型 X 中使用它,然后为 [=] 中定义的每个类型创建实现,我会很好11=]。但是我该怎么做呢?

通过将 generic type parameterX 结合使用,您甚至不需要在实现中键入参数:

TS Playground

type AB = string | number;
type X<T extends AB> = (inp: T) => void;

const x: X<number> = (inp) => {
  inp // number
};

const y: X<string> = (inp) => {
  inp // string
};

编辑:对新问题的回应:

Note that idiomatically-named string enums use PascalCase.

查看代码中的注释:

TS Playground

// Base types:

/**
 * From [Distributive conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types):
 *
 * > ...an instantiation of `T extends U ? X : Y` with
 * > the type argument `A | B | C` for `T` is resolved as
 * > `(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)`.
 *
 * For `T extends unknown ? ...`, see also:
 * https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#example-3
 */
type DistributeUnionToFirstParamInFn<
  U,
  FnReturnType = void,
> = U extends unknown ? ((_: U) => FnReturnType) : never;

type AB = string | number;
const enum Z { X = 'x', Y = 'y'};

// First example:

type MyObj = Record<Z, DistributeUnionToFirstParamInFn<AB>>;

const obj1: MyObj = {
  x: (inp: string) => { console.log('this is a string ', inp) },
  y: (inp: number) => { console.log('this is a number ', inp) },
};

type ParamInObj1X = Parameters<typeof obj1['x']>[0]; // string | number
type ParamInObj1Y = Parameters<typeof obj1['y']>[0]; // string | number

// So, not quite what you want. Compare with...
//Second example:

function validateObject <T extends Record<Z, DistributeUnionToFirstParamInFn<AB>>>(value: T): T {
  return value;
}

validateObject({x: (inp: string) => { console.log('this is a string ', inp) }}); /*
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Property 'y' is missing in type... Error (2345) */

validateObject({
  x: (inp: string) => { console.log('this is a string ', inp) },
  y: (inp: boolean) => { console.log('this is a number ', inp) }, /*
  ^
Type '(inp: boolean) => void' is not assignable to type '((_: string) => void) | ((_: number) => void)'... Error (2322) */
});

const obj2 = validateObject({
  x: (inp: string) => { console.log('this is a string ', inp) },
  y: (inp: number) => { console.log('this is a number ', inp) },
});

type ParamInObj2X = Parameters<typeof obj2['x']>[0]; // string
type ParamInObj2Y = Parameters<typeof obj2['y']>[0]; // number

//