我正在尝试写这样的东西。为了清楚起见,已对其进行了简化:
interface $ {
frameWorkMethod<T>(first: T, options: FrameworkMethodOptions<T>): object;
}
interface FrameworkMethodOptions<T> {
aProperty?: string[];
anotherProperty?: boolean;
[P in keyof T]?: OptionsCallBack //THIS GIVES ERROR
}
interface OptionsCallBack {
create?: () => void;
update?: () => void;
}
这个想法是有效的FrameworkMethodOptions<T>
可以是:
有效对象的示例:
var user: User = { name: "leonardo", age: 33 };
interface User {
name: string;
age: number;
}
var example1: FrameworkMethodOptions<any> = {
aProperty: ["this is string", " ignoreThis"]
};
var example2: FrameworkMethodOptions<any> = {
aProperty: ["this is string", " ignoreThis"],
age: { create: () => { console.log("ah") } }
};
var example3: FrameworkMethodOptions<User> = {
aProperty: ["this is string", " ignoreThis"],
age: { create: () => { console.log("ah") } }
};
var example4: FrameworkMethodOptions<User> = {
aProperty: ["this is string", " ignoreThis"],
};
var example5: FrameworkMethodOptions<User> = {
age: { create: () => { console.log("ah") } }
};
var example6: FrameworkMethodOptions<User> = {};
var example7: FrameworkMethodOptions<any> = {};
您可以看到错误,我尝试过的其他替代方法以及在this Typescript Playground
中工作的代码。有一个问题:我正在使用TS 2.3。但是,即使使用最新的TS版本,我也不认为有可能。 背景:Knockout映射是KnockoutJS的插件。我正在尝试改进它的打字稿打字。
答案 0 :(得分:0)
这应该工作,请享受。
如果有任何问题,请告诉我。
type FrameworkMethodOptions2<T> = any extends T
? FrameworkMethodOptionsPart1
: FrameworkMethodOptionsPart1 & FrameworkMethodOptionsPart2<T>
答案 1 :(得分:0)
对我有用的解决方案
interface FrameworkMethodOptionsPart1 {
aProperty?: string[];
anotherProperty?: boolean;
}
type FrameworkMethodOptionsPart2<T> = {
[P in keyof T]?: OptionsCallBack
}
type FrameworkMethodOptions<T> = FrameworkMethodOptionsPart1 | FrameworkMethodOptionsPart2<T>;
对于将来的参考豚鼠,下面是我尝试过的所有替代方法,以防Playground Link停止工作。
您需要将代码复制并粘贴到启用了打字稿的ide /代码编辑器中,以查看错误。
//imagine this is the framework declarations
interface $ {
frameWorkMethod<T>(first: T, options: FrameworkMethodOptions<T>): object;
}
interface FrameworkMethodOptions<T> {
aProperty?: string[];
anotherProperty?: boolean;
[P in keyof T]?: OptionsCallBack;
}
interface OptionsCallBack {
create?: () => void;
update?: () => void;
}
var user: User = { name: "leonardo", age: 33 };
interface User {
name: string;
age: number;
}
var example1: FrameworkMethodOptions<any> = {
aProperty: ["this is string", " ignoreThis"]
};
var example2: FrameworkMethodOptions<any> = {
aProperty: ["this is string", " ignoreThis"],
address: { create: () => { console.log("ah") } }
};
var example3: FrameworkMethodOptions<User> = {
aProperty: ["this is string", " ignoreThis"],
age: { create: () => { console.log("ah") } }
};
var example4: FrameworkMethodOptions<User> = {
aProperty: ["this is string", " ignoreThis"],
};
var example5: FrameworkMethodOptions<User> = {
age: { create: () => { console.log("ah") } }
};
var example6: FrameworkMethodOptions<User> = {};
var example7: FrameworkMethodOptions<any> = {};
var invalidExample1: FrameworkMethodOptions<User> = {
address: { create: () => { console.log("ah") } } //Address ist not part of User interface
};
////////////////////////////////////////////////////////////////////
//B Alternative Idea
interface FrameworkMethodOptionsPart1 {
aProperty?: string[];
anotherProperty?: boolean;
}
type FrameworkMethodOptionsPart2<T> = {
[P in keyof T]?: OptionsCallBack
}
type FrameworkMethodOptionsB<T> = FrameworkMethodOptionsPart1 & FrameworkMethodOptionsPart2<T>;
var example1b: FrameworkMethodOptionsB<any> = {
aProperty: ["this is string", " ignoreThis"]
};
var example2b: FrameworkMethodOptionsB<any> = {
aProperty: ["this is string", " ignoreThis"],
address: { create: () => { console.log("ah") } }
};
var example3b: FrameworkMethodOptionsB<User> = {
aProperty: ["this is string", " ignoreThis"],
age: { create: () => { console.log("ah") } }
};
var example4b: FrameworkMethodOptionsB<User> = {
aProperty: ["this is string", " ignoreThis"],
};
var example5b: FrameworkMethodOptionsB<User> = {
age: { create: () => { console.log("ah") } }
};
var example6b: FrameworkMethodOptionsB<User> = {};
var example7b: FrameworkMethodOptionsB<any> = {};
var invalidExample1b: FrameworkMethodOptionsB<User> = {
address: { create: () => { console.log("ah") } } //Address is not part of User interface
};
/////////////////////////////////////////////////////////////////
// C Alternative Idea
type FrameworkMethodOptionsC<T> = any extends T
? FrameworkMethodOptionsPart1
: FrameworkMethodOptionsPart1 & FrameworkMethodOptionsPart2<T>;
var example1c: FrameworkMethodOptionsC<any> = {
aProperty: ["this is string", " ignoreThis"]
};
var example2c: FrameworkMethodOptionsC<any> = {
aProperty: ["this is string", " ignoreThis"],
address: { create: () => { console.log("ah") } }
};
var example3c: FrameworkMethodOptionsC<User> = {
aProperty: ["this is string", " ignoreThis"],
age: { create: () => { console.log("ah") } }
};
var example4c: FrameworkMethodOptionsC<User> = {
aProperty: ["this is string", " ignoreThis"],
};
var example5c: FrameworkMethodOptionsC<User> = {
age: { create: () => { console.log("ah") } }
};
var example6c: FrameworkMethodOptionsC<User> = {};
var example7c: FrameworkMethodOptionsC<any> = {};
var invalidExample1c: FrameworkMethodOptionsC<User> = {
address: { create: () => { console.log("ah") } } //Address is not part of User interface
};
/////////////////////////////////////////////////////////////////
// D Alternative Idea
type FrameworkMethodOptionsPart2Untyped = {
[key: string]: OptionsCallBack // TS DOESNT ALLOW THIS TO BE OPTIONAL
}
type FrameworkMethodOptionsD<T> = any extends T
? FrameworkMethodOptionsPart1 & FrameworkMethodOptionsPart2Untyped
: FrameworkMethodOptionsPart1 & FrameworkMethodOptionsPart2<T>;
var example1d: FrameworkMethodOptionsD<any> = {
aProperty: ["this is string", " ignoreThis"]
};
var example2d: FrameworkMethodOptionsD<any> = {
aProperty: ["this is string", " ignoreThis"],
address: { create: () => { console.log("ah") } }
};
var example3d: FrameworkMethodOptionsD<User> = {
aProperty: ["this is string", " ignoreThis"],
age: { create: () => { console.log("ah") } }
};
var example4d: FrameworkMethodOptionsD<User> = {
aProperty: ["this is string", " ignoreThis"],
};
var example5d: FrameworkMethodOptionsD<User> = {
age: { create: () => { console.log("ah") } }
};
var example6d: FrameworkMethodOptionsD<User> = {};
var example7d: FrameworkMethodOptionsD<any> = {};
var invalidExample1d: FrameworkMethodOptionsD<User> = {
address: { create: () => { console.log("ah") } } //Address is not part of User interface
};
/////////////////////////////////////////////////////////////////
// E Alternative Idea
type FrameworkMethodOptionsE<T> = FrameworkMethodOptionsPart1 & FrameworkMethodOptionsPart2Untyped
var example1e: FrameworkMethodOptionsE<any> = {
aProperty: ["this is string", " ignoreThis"]
};
var example2e: FrameworkMethodOptionsE<any> = {
aProperty: ["this is string", " ignoreThis"],
address: { create: () => { console.log("ah") } }
};
var example3e: FrameworkMethodOptionsE<User> = {
aProperty: ["this is string", " ignoreThis"],
age: { create: () => { console.log("ah") } }
};
var example4e: FrameworkMethodOptionsE<User> = {
aProperty: ["this is string", " ignoreThis"],
};
var example5e: FrameworkMethodOptionsE<User> = {
age: { create: () => { console.log("ah") } }
};
var example6e: FrameworkMethodOptionsE<User> = {};
var example7e: FrameworkMethodOptionsE<any> = {};
var invalidExample1e: FrameworkMethodOptionsE<User> = {
address: { create: () => { console.log("ah") } } //Address is not part of User interface
};
/////////////////////////////////////////////////////////////////
// F Alternative Idea. THIS ONE WORKS. !!!!!!!!!!!!!!!!!!!!!!!!!
type FrameworkMethodOptionsF<T> = FrameworkMethodOptionsPart1 | FrameworkMethodOptionsPart2<T>;
var example1f: FrameworkMethodOptionsF<any> = {
aProperty: ["this is string", " ignoreThis"]
};
var example2f: FrameworkMethodOptionsF<any> = {
aProperty: ["this is string", " ignoreThis"],
address: { create: () => { console.log("ah") } },
anythingGoes: 42
};
var example3f: FrameworkMethodOptionsF<User> = {
aProperty: ["this is string", " ignoreThis"],
age: { create: () => { console.log("ah") } }
};
var example4f: FrameworkMethodOptionsF<User> = {
aProperty: ["this is string", " ignoreThis"],
};
var example5f: FrameworkMethodOptionsF<User> = {
age: { create: () => { console.log("ah") } }
};
var example6f: FrameworkMethodOptionsF<User> = {};
var example7f: FrameworkMethodOptionsF<any> = {};
var invalidExample1f: FrameworkMethodOptionsF<User> = {
address: { create: () => { console.log("ah") } } //Expect error. Address is not part of User interface
};
var invalidExample2f: FrameworkMethodOptionsF<User> = {
age: { create: () => { console.log("ah") } },
address: { create: () => { console.log("ah") } } //Expect error. Address is not part of User interface
};
var invalidExample3f: FrameworkMethodOptionsF<User> = {
aProperty: ["this is string", " ignoreThis"],
address: { create: () => { console.log("ah") } } //Expect error. Address is not part of User interface
};
var invalidExample4f: FrameworkMethodOptionsF<User> = {
aProperty: 42, //Expect error. aProperty's type is string[]
};