打字稿:对象类型到数组类型(元组)

Nur*_*yev 6 tuples typescript

我有这个:

interface Obj {
    foo: string,
    bar: number,
    baz: boolean
}
Run Code Online (Sandbox Code Playgroud)

所需的类型是这个元组:

[string, number, boolean]
Run Code Online (Sandbox Code Playgroud)

如何将接口转换为元组?

更新:

我最初的问题是:我用声明式的精神制作了一些自以为是的库,用户应该在对象文字中描述函数的参数。像这样:

let paramsDeclaration = {
  param1: {
    value: REQUIRED<string>(),
    shape: (v) => typeof v === 'string' && v.length < 10
  },
  param2: {
    value: OPTIONAL<number>(),
    ...
  },
}
Run Code Online (Sandbox Code Playgroud)

然后库接受这个对象并创建一个带有参数的函数:

   (param1: string, param2?: number) => ...
Run Code Online (Sandbox Code Playgroud)

所以,制作这样的功能不是问题,问题是正确键入它,以便用户获得良好的代码完成(IntelliSense)。

PS我知道它无法解决,但是知道什么是最接近的解决方法/hack会很有趣。

kay*_*ya3 6

90% 的时间你认为在 Typescript 中有些事情是不可能的,真正的答案是它是可能的,但你可能不应该这样做。

这是使用此答案的TuplifyUnion解决方案,它将联合类型转换为元组类型;请注意,我们需要从对象的键的联合开始,而不是从其值开始,因为值本身可能是联合(例如,技术上是)。booleantrue | false

阅读链接的答案以详细说明该// oh boy don't do this评论的含义。如果您希望 API 的用户指定 API 生成的函数的参数,那么明智的选择是首先接受数组中的这些参数规范。

type ObjValueTuple<T, KS extends any[] = TuplifyUnion<keyof T>, R extends any[] = []> =
  KS extends [infer K, ...infer KT]
  ? ObjValueTuple<T, KT, [...R, T[K & keyof T]]>
  : R

// type Test = [string, number, boolean]
type Test = ObjValueTuple<Obj>
Run Code Online (Sandbox Code Playgroud)

游乐场链接


小智 3

这并不是问题的答案,但由于我实际上认为不可能做到这一点,希望这至少在某种程度上有帮助:

function REQUIRED<T>(): T {
    //...
}
function OPTIONAL<T>(): T {
    //...
}

interface ParamsDeclaration {
    readonly [paramName: string]: {
        readonly value: any;
        readonly shape?: Function;
    };
}

type Func<T> = T extends {
    readonly [paramName: string]: {
        readonly value: infer U;
    };
} ? (...params: Array<U>) => void
    : never;

function create<T extends ParamsDeclaration>(paramsDeclaration: T): Func<T> {

    // ...
}

const paramsDeclaration = {
    param1: {
        value: REQUIRED<string>(),
        shape: (v: any) => typeof v === 'string' && v.length < 10
    },
    param2: {
        value: OPTIONAL<number>(),
        //...
    },
};
// Type is '(...params: (string | number)[]) => void'
const func1 = create(paramsDeclaration);
func1('1', 2); // Ok
func1(2, '1'); // Ok, but I assume not what you want
func1(Symbol()); // TS error
Run Code Online (Sandbox Code Playgroud)