Javascript TS:通常如何通过参数属性获取返回对象的类型

Javascript TS:通常如何通过参数属性获取返回对象的类型,javascript,typescript,generics,Javascript,Typescript,Generics,假设我们有以下类型 type ALL = 'AA' | 'BB' | 'CC'; type AA = { a: number; }; type BB = { b: string; }; type CC = { c: boolean; }; type MyArg = { type: ALL }; 我尝试为类型创建映射器,例如 函数钩子必须返回对象,这取决于参数类型 const hook = (g: MyArg) => { const some = {}; ...// some ca

假设我们有以下类型

type ALL = 'AA' | 'BB' | 'CC';
type AA = { a: number; };
type BB = { b: string; };
type CC = { c: boolean; };
type MyArg = { type: ALL };
我尝试为类型创建映射器,例如

函数钩子必须返回对象,这取决于参数类型

const hook = (g: MyArg) => {
  const some = {};
  ...// some calculations here
  return some as ReturnMap[g.type];
};
但是用return语句捕获行上的TS错误

Type 'any' cannot be used as an index type.
如果修改了,就这样返回

const hook = (g: MyArg) => {
  const some = {};
  ...// some calculations here
  return some as ReturnMap[typeog g['type']];
};
case中返回的对象的类型

const answ = hook({ type: 'BB' });

将是AA | BB | CC,但我只想BB

请记住,将程序编译为JavaScript时,TypeScript的类型系统会运行。当它出现在JavaScript中时,几乎所有类型都会从代码中消失

此外,在运行编译后的JavaScript程序之前,代码中的值是未知的,而在TypeScript编译器完成其工作之后很久

因此,您不能使类型依赖于在程序运行之前未知的值。唯一可以影响类型的值是在任何代码实际运行之前在代码编辑器中缩小的值

你可以做一些你正在尝试做的事情,但我怀疑它不会有任何接近你所寻求的功能:

var map: {
    'AA': { a: number },
    'BB': { b: string },
    'CC': { c: boolean }
};

function h<T extends 'AA' | 'BB' | 'CC'>(ty: T): typeof map[T] {
    return {} as any;
}


var q = h('BB');
// q is of type { b: string } but only because argument ty was given as string literal of specific value

在这里你可以看到。请注意编译后的JavaScript代码是如何缺少所有类型信息和与类型相关的任何逻辑的。

通过以下方式解决了这个问题

type ReqTypes = 'AA' | 'BB';
type ReqGenModel = {
  msg: string;
  type: ReqTypes;
};

type ReqGen1Props = { a: string, b: string };
const reqGen1 = (props: ReqGen1Props): ReqGenModel => {
  return {
    msg: props.a + props.b,
    type: 'AA',
  };
};

type ReqGen2Props = { a: string };
const reqGen2 = (props: ReqGen2Props): ReqGenModel => {
  return {
    msg: props.a + '-DEFAULT',
    type: 'BB',
  };
};
然后用重载定义getHook函数

const c = (x: any): unknown => c;

function getHook(arg: ReturnType<typeof reqGen1>): AA;
function getHook(arg: ReturnType<typeof reqGen2>): BB;
function getHook(arg) {
  const b = c(arg);

  return b;
};
更新:

type ResReturn<T> = T extends ReturnType<typeof reqGen1>
  ? AA
  : T extends ReturnType<typeof reqGen2>
    ? BB
    : never;

function getHookV2<T>(arg: T): ResReturn<T> {
  const b: any = c(arg);

  return b;
};

const hhh = getHookV2(reqGen1({a: 'ggg', b: 'cc'}));
// const hhh: AA

如果您提前定义了reqGen1和reqGen2的返回类型,并为它们命名,可能会更简洁。
const ty = getHook(reqGen1({a: 'ggg', b: 'cc'}));
// const ty: AA
enter code here
type ResReturn<T> = T extends ReturnType<typeof reqGen1>
  ? AA
  : T extends ReturnType<typeof reqGen2>
    ? BB
    : never;

function getHookV2<T>(arg: T): ResReturn<T> {
  const b: any = c(arg);

  return b;
};

const hhh = getHookV2(reqGen1({a: 'ggg', b: 'cc'}));
// const hhh: AA