如何解决打字稿省略getter setter readOnly for Partial data?
如何在 Partial<>
数据中省略getter、setter、methods?
或者有没有办法用打字稿获得这种架构?
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,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) {
内能够使用所有公共道具方法、getter、setter。
并且在 function create(data?: Partial<A>)
中只允许部分数据(没有 getter、setter、methods)。
所以当我使用 create()
时,我想要一个技巧来在这里只获取黄色道具
我尝试了很多场景都没有成功,总是在某处碰壁!如果你有另一种方式来构建这个? 谢谢
解决方法
据我所知,您无法在类型系统中检测 getter 或 setter;有关详细信息,请参阅 microsoft/TypeScript#10196。 said 那里
接口在常规属性和访问器属性之间没有区别——这是一个留给接口实现者的实现细节。
如果您想检测其值是函数类型的属性,您可以使用 this question 的答案中的 KeysMatching
:
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 的属性计数),您可以使用 this question 的答案中的 ReadonlyKeys
来实现:
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
中的东西。如果是这样,您可以使用 the same question with ReadonlyKeys
的答案中的 OptionalKeys
类型:
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;
} */
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。