Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
typescript动态类型和泛型_Typescript_Typescript Generics - Fatal编程技术网

typescript动态类型和泛型

typescript动态类型和泛型,typescript,typescript-generics,Typescript,Typescript Generics,我很难理解typescript动态(和泛型)类型 我试图实现的是创建一个函数,该函数返回一个具有特定类型的对象,其中该对象的某些属性必须匹配给定给该函数的任何参数 所以,基本上我想要发生什么(伪): const listRequest=createRequest('list',{id:[1,2]}) 此函数应按如下方式创建一个对象: { operationVersion: 1, protocolVersion: 2, operation: 'list', // first param

我很难理解typescript动态(和泛型)类型

我试图实现的是创建一个函数,该函数返回一个具有特定类型的对象,其中该对象的某些属性必须匹配给定给该函数的任何参数

所以,基本上我想要发生什么(伪):

const listRequest=createRequest('list',{id:[1,2]})

此函数应按如下方式创建一个对象:

{
  operationVersion: 1,
  protocolVersion: 2,
  operation: 'list', // first param
  list: {            // prop name must match with first param
    ids: [1, 2],     // second param
  }
}
目前,我的代码如下所示:

interface IBaseRequest {
  operationId: number;
  protocolVersion: number;
  operation: string;
  authenticationToken?: string;
}

export type BaseRequest<Operation extends string> = {
  [Prop in keyof IBaseRequest]: IBaseRequest[Prop];
} & Record<Operation, any>;

type CreateRequestType = <T extends string>(operation: string, params: any) => BaseRequest<T>;

export const createRequest: CreateRequestType = <T extends string>(operation: string, params: any) => {

  const req = {
    operation: operation,
    operationId: 1,
    protocolVersion: 2,
  };

  req[operation] = params;
  return req as BaseRequest<T>;
};

我得到一个错误:

Conversion of type 'BaseRequest<string>' to type '"list"' may be a mistake
because neither type sufficiently overlaps with the other. If this was
intentional, convert the expression to 'unknown' first.ts(2352)
将“BaseRequest”类型转换为“list”类型可能是错误的
因为两种类型都没有足够的重叠。如果这是
有意的,首先将表达式转换为“未知”。ts(2352)

有没有办法用类型和泛型来实现这一点?

这样的函数很难用TypeScript编码。以下替代版本更简单、更简洁,只需一个“聚合”输入参数,在您的示例中,它将是
{list:{a:'aa'}

function createRequestBis<K extends string, T>(payload: { [k in K]: T }) {
    const operation = Object.keys(payload)[0] as K;
    return Object.assign({
        operationVersion: 1,
        protocolVersion: 2,
        operation,
    }, payload);
}

const listRequest = createRequestBis({ list: { a: 'aa' } });
listRequest; // Type { operationVersion: number... } & { list: { a: string } } -> True but ugly!
listRequest.operation; // Type "list" -> OK
listRequest.list.a;    // Type "string" -> OK
函数createRequestBis(有效负载:{[k in k]:T}){
常量操作=对象键(有效载荷)[0]作为K;
返回Object.assign({
操作版本:1,
协议版本:2,
活动
},有效载荷);
}
const listRequest=createRequestBis({list:{a:'aa'}});
listRequest;//键入{operationVersion:number…}&{list:{a:string}}->True但丑陋!
listRequest.operation;//键入“列表”->OK
listRequest.list.a;//键入“字符串”->OK
它可以工作,但所推断的返回类型有点难看。我们可以使用自定义实用程序类型对其进行增强,该类型可解构并重构对象类型:

type Prettify<T> = T extends infer Tb ? { [K in keyof Tb]: Tb[K] } : never;

const header = {
    operationVersion: 1,
    protocolVersion: 2
};

function createRequestPretty<K extends string, T>(payload: { [k in K]: T }) {
    const operation = Object.keys(payload)[0] as K;
    const result = Object.assign({ operation }, header, payload);
    return result as any as Prettify<typeof result>;
}

const listRequest2 = createRequestPretty({ list: { a: 'aa' } });
listRequest2; // Type { operation: "list"; operationVersion: number; protocolVersion: number; list: { a: string } } -> OK
type Prettify=T扩展推断Tb?{[K-in-keyof-Tb]:Tb[K]}:从不;
常数头={
操作版本:1,
协议版本:2
};
函数createRequestPretty(有效负载:{[k in k]:T}){
常量操作=对象键(有效载荷)[0]作为K;
const result=Object.assign({operation},header,payload);
以任何形式返回结果作为美化;
}
const listRequest2=createRequestPretty({list:{a:'aa'}});
listRequest2;//键入{operation:“list”;operationVersion:编号;protocolVersion:编号;list:{a:string}}->OK

这是否可能不起作用,因为它打算使用
iBasereRequest
作为类而不是接口?@sandrooco这对我来说真的不重要,只要最终结果是带有intellisense的X类型的对象:)我对类型脚本类型和泛型相当陌生
type Prettify<T> = T extends infer Tb ? { [K in keyof Tb]: Tb[K] } : never;

const header = {
    operationVersion: 1,
    protocolVersion: 2
};

function createRequestPretty<K extends string, T>(payload: { [k in K]: T }) {
    const operation = Object.keys(payload)[0] as K;
    const result = Object.assign({ operation }, header, payload);
    return result as any as Prettify<typeof result>;
}

const listRequest2 = createRequestPretty({ list: { a: 'aa' } });
listRequest2; // Type { operation: "list"; operationVersion: number; protocolVersion: number; list: { a: string } } -> OK