gpt4 book ai didi

typescript - 创建一个类型,该类型是对象属性的数组

转载 作者:搜寻专家 更新时间:2023-10-30 21:33:23 26 4
gpt4 key购买 nike

所以我试图获得这种行为:

interface A {
prop1: string;
prop2: number;
prop3: boolean;
}

type PropertyArray<T> = magical code

// PropertyArray<A> should be the same as the type ['prop1', 'prop2', 'prop3']

const properties: PropertyArray<A> = ['prop1', 'prop2', 'prop3'];

const fail1: PropertyArray<A> = ['prop1', 'prop2']; // type error
const fail2: PropertyArray<A> = ['prop1', 'prop1', 'prop2', 'prop3']; // type error

这段代码的要点是,如果我在接口(interface) A 中添加一个新字段,我还需要将该属性包含到数组中。如果缺少任何属性,构建将失败。

感谢您的帮助。

最佳答案

如果您真的关心属性顺序,那么这实际上是 this question about turning a union into a tuple 的副本如果你定义

type PropertyArray<T> = TuplifyUnion<keyof T>

但希望您真的不关心属性顺序,并且['prop2', 'prop1', 'prop3']将是一个可接受的值 properties .在这种情况下,我可以想到两种方法:


一种是实际计算PropertyArray<T>如您所问,作为元组中所有可能的键排列的并集。这自然会涉及循环条件类型 which is not currently supported .相反,我可以定义一个支持具有最多固定数量属性的类型的定义,如下所示:

type PropertyArray<T> = Tup<keyof T>
type Cons<H, T extends any[]> = T extends any ? ((h: H, ...t: T) => void) extends ((...r: infer R) => void) ? R : never : never
type Tup<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup1<Exclude<V, U>>> : never
type Tup1<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup2<Exclude<V, U>>> : never
type Tup2<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup3<Exclude<V, U>>> : never
type Tup3<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup4<Exclude<V, U>>> : never
type Tup4<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup5<Exclude<V, U>>> : never
type Tup5<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup6<Exclude<V, U>>> : never
type Tup6<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup7<Exclude<V, U>>> : never
type Tup7<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup8<Exclude<V, U>>> : never
type Tup8<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, Tup9<Exclude<V, U>>> : never
type Tup9<U, V = U> = [U] extends [never] ? [] : U extends any ? Cons<U, TupX<Exclude<V, U>>> : never
type TupX<U> = [] // bail out

对于你的情况:

interface A {
prop1: string;
prop2: number;
prop3: boolean;
}

const properties: PropertyArray<A> = ['prop1', 'prop2', 'prop3'];
const fail1: PropertyArray<A> = ['prop1', 'prop2']; // type error
const fail2: PropertyArray<A> = ['prop1', 'prop1', 'prop2', 'prop3']; // type error

这可以按您想要的方式工作,但对编译器来说需要大量工作并且可能很脆弱。


一个不太疯狂的解决方案(仍然有点疯狂)是使用辅助函数而不是类型别名。辅助函数只有在其参数包含相关对象类型的每个键恰好一次时才会编译:

type TupleHasRepeats<T extends any[]> = { [I in keyof T]: T[I] extends T[Exclude<keyof T, keyof any[] | I>] ? unknown : never}[number] 

const propertyArray = <T>() => <A extends Array<keyof T>>(...a: A & (keyof T extends A[number] ? unknown : never) & (unknown extends TupleHasRepeats<A> ? never : unknown )) => a;

然后尝试一下:

interface A {
prop1: string;
prop2: number;
prop3: boolean;
}

const propertyArrayA = propertyArray<A>();

const properties = propertyArrayA('prop1', 'prop2', 'prop3');
const fail1 = propertyArrayA('prop1', 'prop2'); // type error;
const fail2 = propertyArrayA('prop1', 'prop1', 'prop2', 'prop3'); // type error

这也行。如果我必须在生产代码中做任何事情,我可能会使用后者。


好的,希望对你有帮助;祝你好运!

关于typescript - 创建一个类型,该类型是对象属性的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55893620/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com