为了对提供给我的类构造函数之一的数据结构进行类型验证,我一直在努力完成一些 Typescript 正确的推理。
本质上,我的构造函数接收一个包含对象列表的数组,这些对象包含一个(某种)插件的声明和插件的“自定义配置”,每个。
我需要 Typescript 来确保提供的 customConfig
与 defaultConfig
上的类型匹配,但是,我没有运气,甚至没有接近它。
我所做的几次尝试变得非常混乱和荒谬,所以我将附上代码的简单表示,希望有助于表达这个想法:
我希望有人可以提供一些光
type Entry = {
extension: {
defaultConfig: Record<PropertyKey, unknown>
install: any
uninstall: any
},
customConfig: Record<PropertyKey, unknown>
}
function initExtensions<I extends Entry[]>(a: I): void { /* ... */ }
initExtensions([
{
extension: {
defaultConfig: { foo: true },
install: () => {/* ... */ },
uninstall: () => {/* ... */ },
},
customConfig: { foo: true } // <-- SHOULD BE OK
},
{
extension: {
defaultConfig: { bar: 123 },
install: () => {/* ... */ },
uninstall: () => {/* ... */ },
},
customConfig: { bar: true } // <-- Should complain as should be a NUMBER
},
])
答案 0 :(得分:3)
我希望,以下解决方案可以几乎达到您的要求。
int r,c;
cin>>r>>c;
int** p=new int*[r];
for(int i=0;i<r;i++) {
p[i]=new int[c];
}
for(int i=0;i<r;i++) {
delete [] p[i];
}
delete [] p;
答案 1 :(得分:1)
你不能真正做你正在寻找的东西,因为 TypeScript 不支持存在类型。 https://github.com/Microsoft/TypeScript/issues/14466
但是,如果您只想验证它是否正确,您可以为每个条目创建一个小包装器。包装器将允许 TypeScript 推断您的
中每个条目的类型type Entry<T, C extends T> = {
extension: {
defaultConfig: T
install: any
uninstall: any
},
customConfig: C
}
function asEntry<T, C extends T>(entry: Entry<T, C>) { return entry };
function initExtensions(entries: Entry<any, any>[]): void { /* ... */ }
initExtensions([
asEntry({
extension: {
defaultConfig: { foo: true },
install: () => {/* ... */ },
uninstall: () => {/* ... */ },
},
customConfig: { foo: true } // <-- OK
}),
asEntry({
extension: {
defaultConfig: { bar: 123 },
install: () => {/* ... */ },
uninstall: () => {/* ... */ },
},
customConfig: { bar: true } // <-- ERROR
})
])
答案 2 :(得分:1)
Todd Skelton 在他的回答中展示的方法也是我所知道的唯一无样板的解决方案。问题是输入数组中的每个条目都是不同的类型(尽管扩展了 Entry
),需要在通用函数签名中明确表示,以便正确进行类型检查。由于目前无法指定具有 n
个模板参数的函数,因此您最终会遇到如下情况:
type Entry<C> = {
extension: { defaultConfig: C };
customConfig: Partial<C>;
install: any;
uninstall: any;
};
type E<C> = Entry<C>;
function initExtensions<C1,C2,C3,C4,C5>(entries: [E<C1>,E<C2>,E<C3>,E<C4>,E<C5>]): void;
function initExtensions<C1,C2,C3,C4>(entries: [E<C1>,E<C2>,E<C3>,E<C4>]): void;
function initExtensions<C1,C2,C3>(entries: [E<C1>,E<C2>,E<C3>]): void;
function initExtensions<C1,C2>(entries: [E<C1>,E<C2>]): void;
function initExtensions<C1>(entries: [E<C1>]):void;
function initExtensions(entries:E<any>[]): void {
// Initialize your extensions here
}
实际上,它以您希望的方式工作,最多 5 个条目,通过将输入表示为不同长度的元组,而不是将输入表示为一种类型的数组,并且填充了独特的类型。这可能看起来很丑陋和奇怪,但实际上这就是库喜欢 lodash type their variadic functions 的方式,所以它有点必要的邪恶。
当然,没有什么能阻止您生成最多 50 个此签名的差异:它仅用于类型检查,不会反映在您的最终输出中。要么,要么一一传递配置对象:
function initExtension<C>(entry: Entry<C>): void {
// Initialize one extension here
}
initExtension({
extension: { defaultConfig: { foo: true } },
customConfig: { foo: true },
install: () => null,
uninstall: () => null,
});
这仅仅是 Todds 方法的替代方法。