微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Typescript Fluent API - 从每个函数的返回值中省略函数

如何解决Typescript Fluent API - 从每个函数的返回值中省略函数

此问题建立在问题和已接受答案 in this link 的基础上。

我想编写一个表单生成器类,其中使用底层类型 T 来确定可以调用哪些函数。举个例子,假设这是我们想要一个表单的模型:

interface MyFormModel {
    name: string;
    options: number[];
    isPrimary: boolean;
    address: {
        street: string;
        houseNumber: number;
        someArrayThatsRelevantToAddresses: string[];
    }
}

我希望能够为属性 'isPrimary' 创建一个复选框,然后我希望 this 的返回值不包括用于创建复选框的方法,因为没有更多的布尔值剩下的属性可以调用“createCheckBox”。我使用第二个类型参数 K 跟踪哪些属性已经用完。每次使用来自 T 的键调用函数后,K 都会更新,以便我们跟踪哪些键已经用完。这是我的实现:

// T is the model for the form,K will accumulate props from T as we build the form
class FormBuilder<T,K extends Partial<T> = {}> {

    buildCheckBox<NewKey extends BooleanKeysOf<T>>(): FormBuilder<T,AddProp<T,K,NewKey>> {
        return this as any;
    }

    buildBlock<NewKey extends CompoundKeysOf<T>>(key: NewKey): FormBuilder<T,NewKey>> {
        return this as any;
    }

    buildInput<NewKey extends StringOrNumberKeysOf<T>>(): FormBuilder<T,NewKey>> {
        return this as any;
    }

    buildArray<NewKey extends ArrayKeysOf<T>>(): FormBuilder<T,NewKey>> {
        return this as any;
    }

    finishForm(): K extends T ? FormForModel<T> : MissingProps<T,K> { // tells us which props are missing!
        // use childforms to build a complete form
        return 'hello' as any;
    }

    // Get a FormBuilder that accumulates props to build one of the object properties of the parent form
    getChildBuilder<NewKey extends CompoundKeysOf<T>>(): FormBuilder<T[NewKey]> {
        return new FormBuilder();
    }
}

这使用了一些辅助类型:

/**
 * Utility types
 */

// Get from Type T all of the keys that have values of type SomeType
type KeysOfType<T,SomeType> = { [K in keyof T]: T[K] extends SomeType ? K : never }[keyof T]

// Get all keys that are boolean,or string | number,or arrays,or other objects
type BooleanKeysOf<T> = KeysOfType<T,boolean>;
type StringOrNumberKeysOf<T> = KeysOfType<T,string | number>;
type ArrayKeysOf<T> = KeysOfType<T,any[]>;
type CompoundKeysOf<T> = Exclude<KeysOfType<T,object>,ArrayKeysOf<T>>; // get all props that have object types,except arrays

// a type representing the form we're building
type FormForModel<T> = { [K in keyof T]: {} } };

// Add to K another prop that's a part of T
type AddProp<T,K extends Partial<T>,NewKey extends keyof T> = K & { [S in NewKey]: T[S] };

// Which props are missing from K to fill out T?
type MissingProps<T,K extends Partial<T>> = Omit<T,keyof K>;

使用这种方法,可以很容易地将每个函数的类型参数限制为之前没有被调用过的键,直到调用签名变成 NewKey extends never 并且无法进行调用

但是,当函数没有合法值可供调用时,我想从类型签名中完全删除它。我想像这样:

    buildCheckBox<NewKey extends Exclude<BooleanKeysOf<T>,keyof K>>(): MaybeExcludeCheckBox<T,NewKey> {
        return this as any;
    }

type MaybeExcludeCheckBox<T,NewKey extends keyof T> = Exclude<keyof T,NewKey> extends never? Omit<FormBuilder<T,NewKey>>,'buildCheckBox'> : FormBuilder<T,NewKey>>

它的作用是检查是否有任何剩余的布尔属性,如果有则返回 FormBuilder 类型,如果没有,则省略 'buildCheckBox' 属性。但是,有时我想打开或关闭多个功能。每次调用函数时,是否有更简洁的方法添加/删除多个属性

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?