打字稿:-为函数创建泛型,以具有一个键的对象作为值的类型,返回类型为value

时间:2020-07-11 19:16:19

标签: typescript typescript-typings typescript-generics

我正在努力键入该函数。 export type DataAttributeType<T> = BACKEND_PRIMITIVE[T]行下面的代码段抛出错误以下;

我想创建一个接受示例输入并返回示例输出的函数。

示例1:

input:- {"S": "2015-02-18T20:27:36.165Z"}
Output:- "2015-02-18T20:27:36.165Z"

示例2:

input:- {"N": 10 }
Output:- 10

我尝试过的事情:

export const enum DATATYPE {
    S = "S",
    N = "N"
}

type BACKEND_PRIMITIVE = {
    [DATATYPE.S]: string;
    [DATATYPE.N]: number;
};

export type BackendDataAttributeType<T> = {
    [T in DATATYPE]?: BACKEND_PRIMITIVE[T];
};

export type DataAttributeType<T> = BACKEND_PRIMITIVE[T];

export const mapToPlainObject = <T>(
    attribute: BackendDataAttributeType<T>
): DataAttributeType<T> => {
    if (attribute.S) {
        return attribute.S;
    }
    if (attribute.N) {
        return attribute.N;
    }

    throw new Error("Not able to parse attribute");
};

问题是我无法保留与输入相同的返回类型。如果键为S,则返回类型应为字符串。

我们将不胜感激

2 个答案:

答案 0 :(得分:0)

您应该定义允许的基本类型。然后定义您的包装器属性类。然后定义一个从包装类返回基类型的函数。

包装和属性示例

    // The limited set of types for attributes
    type AlllowedAttributeType = string | number | { foo: string, bar: string};

    // Create a rich interface for you data type
    interface MyDataAttributeType<AlllowedAttributeType> {
      name: string;
      data: AlllowedAttributeType;
    }

    // Type of the function that returns the attribute value
    type GetAttributeValue = 
      (input: MyDataAttributeType<AlllowedAttributeType>) => AlllowedAttributeType;

    // Return just the value part
    const myGetTypedData: GetAttributeValue = (input) => {
      return input.data;
    };

用法

    const d1 = {
      name: 'data1',
      data: 1,
    }

    const d2 = {
      name: 'dataTwo',
      data: 'Two',
    }

    const d3 = {
      name: 'complex',
      data: { foo: 'biz', bar: 'baz' }
    }

    console.log(myGetTypedData(d1));
    console.log(myGetTypedData(d2));
    console.log(myGetTypedData(d3));

    const d4 = {
      name: 'error',
      data: { wrong: 'type' },
    }
    // wont compile
    console.log(myGetTypedData(d4));

答案 1 :(得分:0)

我不确定100%地确定您要做什么,但是我的直觉是这样写mapToPlainObject

const mapToPlainObject = <T extends Partial<BACKEND_PRIMITIVE>>(
    attribute: T
): T[keyof T] => {
    return attribute[(Object.keys(attribute) as Array<keyof T>)[0]];
};

在这里,我要说的是,您将传递具有BACKEND_PRIMITIVE某些属性的东西(我想它永远都是这样的属性),它会返回其中之一(如果确实有一个然后返回那个)。 (请注意,Object.keys()在TypeScript中返回string[],但是我断言它将是attribute类型的已知键的数组。从技术上讲,这不是安全的,但是我我假设您的输入中没有多余的意外键。

这提供了您要提及的输入/输出关系,并且编译器知道了输出类型:

const str = mapToPlainObject({ "S": "2015-02-18T20:27:36.165Z" });
// const str: string;
console.log(str); // "2015-02-18T20:27:36.165Z"
const num = mapToPlainObject({ "N": 10 });
// const num: number;
console.log(num); // 10

您可能还有其他用例,它们需要更复杂的类型签名。如果是这样,请将其添加到问题中以便可以解决。否则,希望能有所帮助;祝你好运!

Playground link to code

相关问题