在许多情况下,需要对象类型描述符(自动UI,比如故事书).我似乎找不到一个简单的方法把它们变成类型.

示例:

const buttonProps = {
 name: {kind:"string", empty:false},
 height: {kind:"number", min:20, max:50},
 width: {kind:"number", min:80},
 dark: {kind:"boolean"}
}

我想要回一种类型:

interface ButtonProps {
 name:string;
 height: number;
 width: number;
 dark: boolean;
}

但我被困住了.一旦你开始处理TYPEOF,你就失go 了要工作的价值.我能做的最多就是用Numbers:True替换Kind:"Numbers",因为它是一个props 名称,但我不喜欢这样(它也可以与Numbers:False一起使用).

有什么 idea 吗?

推荐答案

因为对象不是不可变的,所以您丢失了实际的"值",所以类型脚本(例如)推断kindstring,而不是字符串类型"string""number""boolean".如果将as const加到对象文字like this的末尾:

const buttonProps = {
    // ...
} as const;

...您告诉TypeScrip对象是不变的,它将推断字符串文字类型.然后我们就可以着手建造mapped type,从buttonProps推断出你想要的类型:

// A property type in button props
type PropertyEntry = {
    kind: "string" | "number" | "boolean";
    empty?: boolean;
};

// The type for a property (ignoring `empty`, we'll handle that separately)
type PropertyValueType<T extends PropertyEntry> =
    T extends {kind: "string"}
    ? string
    : T extends {kind: "number"}
    ? number
    : T extends {kind: "boolean"}
    ? boolean
    : never;

// The mapped type that accepts the type of an object using `PropertyEntry`
// elements and provides the type that object describes
type PropertiesType<ObjectType extends Record<string, PropertyEntry>> =
    // The non-optional ones (no `empty` or `empty: false`):
    & {
        -readonly [Key in keyof ObjectType as ObjectType[Key] extends {empty: true} ? never : Key]: PropertyValueType<ObjectType[Key]>;
    }
    // The optional ones (`empty: true`):
    & {
        -readonly [Key in keyof ObjectType as ObjectType[Key] extends {empty: true} ? Key : never]?: PropertyValueType<ObjectType[Key]>;
    };

在这里,我使用了各种mapping modifiers,并将可选属性(empty: true)与非可选属性分开处理(这样我就可以将可选修饰符?应用于可选属性).

将其与buttonProps一起使用:

// Testing with `buttonProps` from the question
const buttonProps = {
    name: {kind:"string", empty:false},
    height: {kind:"number", min:20, max:50},
    width: {kind:"number", min:80},
    dark: {kind:"boolean"},
    optionalBool: {kind: "boolean", empty: true} // Added this for testing
} as const;

type ButtonProps = PropertiesType<typeof buttonProps>;
//   ^? type ButtonProps = { name: string, height: number, width: number, dark: boolean} & { optionalBool?: boolean | undefined }

// Test the type
const x: ButtonProps = {
    dark: true,
    name: "x",
    height: 0,
    width: 0,
    // Optional prop not required
};

Playground link

我确信有很多地方需要调整(如果可以更简洁地完成,我也不会感到惊讶),但这是主要的 idea .

Typescript相关问答推荐

根据第一个参数的值设置第二个参数的类型

Typescript问题和缩减器状态不会在单击时添加用途.属性'状态和调度'不存在于userContextType类型上'|null'

错误:note_modules/@types/note/globals.d.ts:72:13 -错误TS 2403:后续变量声明必须具有相同的类型

将对象属性路径描述为字符串数组的类型

如果我有对象的Typescript类型,如何使用其值的类型?

在Angular中,如何在文件上传后清除文件上传文本框

typescript抱怨值可以是未定义的,尽管类型没有定义

为什么TypeScript失go 了类型推断,默认为any?''

将对象属性转换为InstanceType或原样的强类型方法

如何在编译时为不带常量的参数引发错误

在数据加载后,如何使用NgFor在使用异步管道的可观测对象上生成子组件?

如何避免推断空数组

Angular文件上传到Spring Boot失败,多部分边界拒绝

常量类型参数回退类型

基元类型按引用传递的解决方法

S,为什么我的T扩展未定义的条件在属性的上下文中不起作用?

字幕子集一个元组的多个元素

如何创建一个将嵌套类属性的点表示法生成为字符串文字的类型?

有没有什么方法可以使用ProvideState()提供多个削减器作为根减减器

是否可以使用元组中对象的键来映射类型