javascript - Typescript 忽略部分数据的 getters setters 只读?

标签 javascript typescript api-design entity-component-system

如何在 Partial<> 中省略 getters、setters、methods数据?

或者存在一种使用 typescript 获得这种架构的方法吗?

我需要一个具有完全访问权限的类型和一个没有只读权限的类型。

我尝试在这里做一个小例子,请参阅 note://

export const $A = (() => {
    class A {
        _uid?: string = 'generateUID()';
        _title?: string = '';
        children?: A[] = [];
        B?: InstanceType<typeof $B['B']> = $B.create();
        get Title() {
            return this._title || this._uid;
        }
        constructor(data: Partial<A> = {}) {
            Object.assign(this, data);
        }
        getFullTitle() {
            return this._title + this._uid;
        }
    }
    function create(data?: Partial<A>) {
        return new A(data);
    }
    function renderer(A: A) {
        //#1 Allow full access public A in this renderer entity
        const { Title, _title, _uid } = A; // acces all props autorized here
        const fulltitle = A.getFullTitle(); // acces methods autorized here
        const childTitle = A.children[0]?.Title; // acces child props autorized here
    }

    return {
        create,
        renderer,
        A,
    };
})();
export const $B = (() => {
    class B {
        _foo?: string = '';
        get Foo() {
            return this._foo + 'foo';
        }
        constructor(data: Partial<B> = {}) {
            Object.assign(this, data);
        }
    }
    function create(data?: Partial<B>) {
        return new B(data);
    }
    function renderer(B: B) {}

    return {
        create,
        renderer,
        B,
    };
})();

// API
//#2 Partial props only (omit methods,getter,setter) for a higth level API !
$A.create({ Title: '' }); // should not visible and lint error !
$A.create({ getFullTitle: () => '' }); // should not visible and lint error !
// want allow only this structure for higth API
$A.create({
    _title: '',
    _uid: '',
    B: $B.create(),
    children: [$A.create({ _title: '', _uid: '' }), $A.create({ _title: '', _uid: '' })],
});

我想要的在里面function renderer(A: A) {能够使用所有公共(public) props 方法、getter、setter。 里面function create(data?: Partial<A>)仅允许部分数据(没有 getter、setter、方法)。

所以我想要一个技巧,当我使用 create() 时,在这里只获得黄色 Prop enter image description here

我尝试了很多场景但没有成功,总是在某个地方碰壁!如果你有其他的方式来构建这个? 谢谢

最佳答案

据我所知,您无法检测类型系统中的 getter 或 setter;请参阅microsoft/TypeScript#10196了解更多信息。是said那里有

Interfaces make no distinction between regular properties and accessor properties--it's an implementation detail left up to the implementer of the interface.


如果要检测值为函数类型的属性,可以使用 KeysMatching来自this question的答案:

type KeysMatching<T, V> = { [K in keyof T]-?: T[K] extends V ? K : never }[keyof T];

type MethodKeysOfA = KeysMatching<A, Function>;
// type MethodKeysOfA = "getFullTitle"

如果您想检测标记为 readonly 的属性(仅 getter 属性也算在内),您可以使用 ReadonlyKeys 来执行此操作来自this question的答案:

type IfEquals<X, Y, A = X, B = never> =
    (<T>() => T extends X ? 1 : 2) extends
    (<T>() => T extends Y ? 1 : 2) ? A : B;
type ReadonlyKeys<T> = {
    [P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>

type ReadonlyKeysOfA = ReadonlyKeys<A>
// type ReadonlyKeysOfA = "Title"

然后您可以将这些组合起来生成您的“部分”A :

type MyPartialA = Omit<A, MethodKeysOfA | ReadonlyKeysOfA>
/* type MyPartialA = {
     _uid?: string | undefined;
     _title?: string | undefined;
    children?: A[] | undefined;
    B?: B | undefined;
} */

如果您使用MyPartialA而不是Partial<A>对于 data 的类型create()中的参数,您就会得到您正在寻找的行为:

$A.create({ Title: '' }); // error!
$A.create({ getFullTitle: () => '' }); // error!

$A.create({
    _title: '',
    _uid: '',
    B: $B.create(),
    children: [$A.create({ _title: '', _uid: '' }), $A.create({ _title: '', _uid: '' })],
}); // okay

您也可能想考虑 MyPartialA作为 A 中的一组可选属性。也就是说,您不是排除方法和只读属性,而是包含 A 中可能不存在的内容。 。如果是这样,您可以使用 OptionalKeys输入 the same question with ReadonlyKeys 的答案:

type OptionalKeys<T> = { [K in keyof T]-?:
    ({} extends { [P in K]: T[K] } ? K : never)
}[keyof T];

type OptionalKeysOfA = OptionalKeys<A>;
// type OptionalKeysOfA = "_uid" | "_title" | "children" | "B"

您可以看到这会导致相同的 MyPartialA和以前一样:

type MyPartialA = Pick<A, OptionalKeysOfA>;
/* type MyPartialA = {
   _uid?: string | undefined;
   _title?: string | undefined;
   children?: A[] | undefined;
   B?: B | undefined;
} */

Playground link to code

关于javascript - Typescript 忽略部分数据的 getters setters 只读?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66800632/

相关文章:

javascript - jQuery 未定义的 ajax 函数

javascript - babel,browserify 错误 : using removed babel 5 option base. 阶段

mongodb - 在TS文件中编写mongo shell脚本

angular - ionic 深层链接

prolog - Prolog 3 路比较中的关系运算符符号

azure - 将变量存储在 Azure 逻辑应用中以在下次运行中使用

javascript - 从 ASP.NET MVC View 调用 TypeScript 类方法

javascript - 你如何监听 javascript 中的多个字段更改?

visual-studio - 环境上下文中不允许使用初始化程序

java - 为什么 JavaMail Transport.send() 是静态方法?