首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型记录:对象类型到数组类型(元组)

类型记录:对象类型到数组类型(元组)
EN

Stack Overflow用户
提问于 2018-10-17 12:43:03
回答 3查看 4.4K关注 0票数 11

我有这个:

代码语言:javascript
复制
interface Obj {
    foo: string,
    bar: number,
    baz: boolean
}

所需的类型是这个元组:

代码语言:javascript
复制
[string, number, boolean]

如何将接口转换为元组?

更新:

我最初的问题是:我使用声明性的精神创建了一些固执己见的库,用户应该用对象文字来描述函数的参数。如下所示:

代码语言:javascript
复制
let paramsDeclaration = {
  param1: {
    value: REQUIRED<string>(),
    shape: (v) => typeof v === 'string' && v.length < 10
  },
  param2: {
    value: OPTIONAL<number>(),
    ...
  },
}

然后,库接受这个对象并创建一个函数,其中包含参数:

代码语言:javascript
复制
   (param1: string, param2?: number) => ...

因此,使这样的功能不是一个问题,问题是如何正确地键入它,以便用户获得良好的代码完成(IntelliSense)。

我知道这是不可能解决的,但是想知道什么是最接近的解决办法/黑客是很有趣的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-10-18 15:40:08

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

代码语言:javascript
复制
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
票数 3
EN

Stack Overflow用户

发布于 2021-08-07 19:22:36

90%的时候,你认为某件事在打字稿中是不可能的,真正的答案是它是可能的,但你可能不应该这样做。

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

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

代码语言:javascript
复制
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>

操场连接

票数 4
EN

Stack Overflow用户

发布于 2020-03-19 11:30:17

备选建议,

它需要设置参数的顺序。

代码语言:javascript
复制
interface Param {
    readonly value: any;
    readonly shape?: Function;
}
type Func<T extends Record<string, Param>, orders extends (keyof T)[]> = (...args:{
    [key in keyof orders]:orders[key] extends keyof T ? T[orders[key]]['value']: orders[key];
})=>void;

function create<T extends Record<string, Param>, ORDERS extends (keyof T)[]>(params: T, ...orders:ORDERS): Func<T, ORDERS> {
    return 0 as any;
}

const func1 = create({a:{value:0}, b:{value:''}, c:{value:true}}, 'a', 'b', 'c');
func1(0, '1', true); // ok
func1(true, 0, '1'); // error

带阵列的ParamDeclarations

代码语言:javascript
复制
type Func2<T extends Param[]> = (...args:{
    [key in keyof T]:T[key] extends Param ? T[key]['value'] : T[key]
})=>void;

function create2<T extends Param[], ORDERS extends (keyof T)[]>(...params: T): Func2<T> {
    return 0 as any;
}

const func2 = create2({value:0}, {value:''}, {value:true});
func2(0, '1', true); // ok
func2(true, 0, '1'); // error
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52855145

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档