TypeScript代码基于动态表单的Angular 2 Cookbook章节 - https://angular.io/docs/ts/latest/cookbook/dynamic-form.html
请观察:
问题-base.ts
export class QuestionBase<T>{
value: T;
key: string;
label: string;
required: boolean;
order: number;
controlType: string;
constructor(options: {
value?: T,
key?: string,
label?: string,
required?: boolean,
order?: number,
controlType?: string
} = {}) {
this.value = options.value;
this.key = options.key || '';
this.label = options.label || '';
this.required = !!options.required;
this.order = options.order === undefined ? 1 : options.order;
this.controlType = options.controlType || '';
}
}
多答案-问题-base.ts
import {QuestionBase} from './question-base';
interface AnswerOption {
key: string;
value: string;
}
export class MultiAnswerQuestionBase<T> extends QuestionBase<T> {
answerOptions: AnswerOption[];
constructor(options: {answerOptions?: AnswerOption[]}) {
super(options);
this.answerOptions = options.answerOptions;
}
}
问题-dropdown.ts
import {MultiAnswerQuestionBase} from './multi-answer-question-base';
export class DropdownQuestion extends MultiAnswerQuestionBase<string> {
controlType = 'dropdown';
}
现在我试图像这样实例化DropdownQuestion
:
new DropdownQuestion({
key: 'brave',
label: 'Bravery Rating',
order: 3,
answerOptions: [
{key: 'solid', value: 'Solid'},
{key: 'great', value: 'Great'},
{key: 'good', value: 'Good'},
{key: 'unproven', value: 'Unproven'}
]
});
这里有关于字段键,标签和顺序的TypeScript投诉:
Error:(45, 17) TS2345: Argument of type '{ key: string; label: string; order: number; answerOptions: { key: string; value: string; }[]; }' is not assignable to parameter of type '{ answerOptions?: AnswerOption[]; }'.
Object literal may only specify known properties, and 'key' does not exist in type '{ answerOptions?: AnswerOption[]; }'.
我理解这个错误的含义,我可以通过引入更多类并使我的代码更类似于C#或Java来解决它,或者只是抛弃所有类型并将其保留为JavaScript。我怀疑,这两种方式都不是TypeScript方式。
那么,TypeScript修复它的方法是什么?
答案 0 :(得分:1)
你真的有几个选择。由于您正在处理对象文字,因此它受excess property checks的约束,这阻止您进行该调用。文档告诉你如何解决这个问题。
使用类型断言
new DropdownQuestion({
key: 'brave',
label: 'Bravery Rating',
order: 3,
answerOptions: [
{key: 'solid', value: 'Solid'},
{key: 'great', value: 'Great'},
{key: 'good', value: 'Good'},
{key: 'unproven', value: 'Unproven'}
]
} as {answerOptions?: AnswerOption[]});
将字符串索引签名添加到类型
constructor(options: {answerOptions?: AnswerOption[], [propName: string]: any}) {
不要在呼叫站点使用对象字面值,将params放在单独的变量中
let options = {
key: 'brave',
label: 'Bravery Rating',
order: 3,
answerOptions: [
{key: 'solid', value: 'Solid'},
{key: 'great', value: 'Great'},
{key: 'good', value: 'Good'},
{key: 'unproven', value: 'Unproven'}
]
};
new DropdownQuestion(options);
但说实话,我没有看到首先拥有所有这些额外属性的重点,它们甚至没有使用过。他们应该被删除。
请记住,由于原始示例在类型注释中使用了{}
,因此它有效地接受了任何对象,但没有已知的命名属性。它使用索引器来访问安全的属性,因为所有对象的成员都可以通过索引访问。此处的多余属性检查不适用,因为注释中未显示任何命名属性。由于您现在更改了签名,因此您现在收到错误。
如果您想完全理解该问题,请参阅GitHub上的issue 3755。如果要在不使用上述建议的情况下使其工作,则应遵循示例模式并使用索引器访问对象的成员。否则,请使用经过验证的解决方案并将其他属性添加到签名中,并取消“部分”签名。
答案 1 :(得分:0)
鉴于您在构造函数中定义了文字类型,最好将所有这些类型传递给子类。正如您所料,创建更多的类/接口,使其类似于C#/ Java。
对于介绍新选项的每个类,请创建包含特定数据的新选项类型。
export class QuestionBaseOptions<T> {
value?: T;
key?: string;
label?: string;
required?: boolean;
order?: number;
controlType?: string;
};
export class QuestionBase<T>{
value: T;
key: string;
label: string;
required: boolean;
order: number;
controlType: string;
constructor(options: QuestionBaseOptions<T> = {}) {
this.value = options.value;
this.key = options.key || '';
this.label = options.label || '';
this.required = !!options.required;
this.order = options.order === undefined ? 1 : options.order;
this.controlType = options.controlType || '';
}
}
interface AnswerOption {
key: string;
value: string;
}
export interface MultiAnswerQuestionBaseOptions<T> extends QuestionBaseOptions<T> {
answerOptions?: AnswerOption[];
}
export class MultiAnswerQuestionBase<T> extends QuestionBase<T> {
answerOptions: AnswerOption[];
constructor(options: MultiAnswerQuestionBaseOptions<T>) {
super(options);
this.answerOptions = options.answerOptions;
}
}
export class DropdownQuestion extends MultiAnswerQuestionBase<string> {
controlType = 'dropdown';
}
new DropdownQuestion({
key: 'brave',
label: 'Bravery Rating',
order: 3,
answerOptions: [
{key: 'solid', value: 'Solid'},
{key: 'great', value: 'Great'},
{key: 'good', value: 'Good'},
{key: 'unproven', value: 'Unproven'}
]
});
&#13;