javascript - 打字稿省略getter setter readOnly for Partial数据?
问题描述
我如何在数据中省略getter、setter 和方法Partial<>
?
还是存在一种使用 typescript 获得这种架构的方法?
我需要一个具有完全访问权限的类型,以及一个没有 readOnly 的类型。
我试着在这里做一个小例子,见注://
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) {
能够使用所有公共道具方法,getter,setter。并且里面function create(data?: Partial<A>)
只允许部分数据(没有getter,setter,methods)。
所以我想要一个技巧来在这里只获得黄色道具,当我使用时create()
我尝试了许多没有成功的场景,总是在某个地方撞墙!如果您有其他方式来构建它?谢谢
解决方案
据我所知,您无法在类型系统中检测到 getter 或 setter。有关详细信息,请参阅microsoft/TypeScript#10196。据说那里_
接口在常规属性和访问器属性之间没有区别——它是一个实现细节,留给接口的实现者。
如果要检测其值是函数类型的属性,可以使用KeysMatching
from the answer to 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
从这个问题的答案中执行此操作:
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>
的类型in ,您将获得您正在寻找的行为: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
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;
} */
推荐阅读
- android - 我需要用于 Firebase 数据库的 Firebase Core 吗?
- css - 带有 ::before 和 z-index 的偏移标头突出显示——仅限 CSS
- python - asyncio - 多次等待协程(周期性任务)
- java - 在不添加额外的 readLine 的情况下读取字符后无法获取下一个输入
- editor - 可重新排序的列表项的可重新排序列表?(编辑)
- raspberry-pi - 任何可以与 HDMI 自动切换一起使用的 Raspberry Pi 替代品?
- javascript - 反应原生创建模块 - 不变违规:元素
- reactjs - 由于第二个同级组件的更改,如何重新渲染一个同级组件
- c++ - 不在构造函数中运行 std::thread
- sql-server - SQL计算资历开始日期