2016-08-28 2 views
1

код машинописи основан на угловой 2 Cookbook главы о динамических формах - https://angular.io/docs/ts/latest/cookbook/dynamic-form.htmlКак правильно указать партитуры объектов в TypeScript?

Пожалуйста, соблюдайте:

вопросительного 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'} 
    ] 
}); 

А вот машинопись жалобы о ключевых полей, этикетки и порядок:

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[]; }'. 

Я понимаю смысл этой ошибки, и я могу ее исправить, вводя больше классов и сделав мой код более похожим t o C# или Java или просто выбросить все типы и оставить его JavaScript. Я подозреваю, что это тоже не тип TypeScript.

Итак, что такое способ TypeScript для его исправления?

+1

Так как вы имеете дело с литералами объектов, оно подлежит [чеки избытка собственности] (https://www.typescriptlang.org/docs/handbook/interfaces.html # over-property-checks), что мешает вам совершить этот вызов. Посмотрите документацию, она расскажет вам, как вы можете обойти это. –

+0

Вызов функции? – mark

ответ

1

У вас есть пара вариантов. Поскольку вы имеете дело с объектными литералами, оно подлежит excess property checks, что мешает вам совершить этот звонок. Документы расскажут вам, как обойти это.

  1. использовать утверждение типа

    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[]}); 
    
  2. добавить индекс строки подписи к типу

    constructor(options: {answerOptions?: AnswerOption[], [propName: string]: any}) { 
    
  3. не использовать литерал объекта в месте вызова, поставить 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); 
    

Но, честно говоря, я не вижу смысла иметь все эти дополнительные свойства, в первую очередь, они даже не используются. Их следует удалить.


Имейте в виду, что так как исходный пример, используемый {} в аннотации типа, он фактически принятой любой объект, но без известных именованных свойств. Он использовал индексаторы для доступа к свойствам, которые безопасны, так как к ним могут обращаться объекты всех объектов по индексу. Проверка избыточного имущества здесь не применяется, поскольку в аннотации не появилось никаких свойств. Поскольку вы изменили подпись, чтобы иметь их сейчас, вы получаете ошибку.

Если вы хотите полностью понять проблему, обратитесь к issue 3755 на GitHub.Если вы хотите, чтобы он работал без использования приведенных выше предложений, вы должны следовать шаблону примера и использовать индексаторы для доступа к членам ваших объектов. В противном случае перейдите к проверенному решению и добавьте эти другие свойства в подпись и покончите с «частичной» подписью.

+0

Что вы имеете в виду в своем последнем заявлении? Что не используется? – mark

+0

Для вашего конструктора требуется объект, который имеет необязательное свойство 'answerOptions' типа' AnswerOption [] '. Но вы вызываете его, используя литерал объекта с дополнительными свойствами. Какая цель это служит? Конструктор бесполезен для него, и машинописный текст говорит вам, что это включение не кажется правильным, и это не так. Как и те же причины, почему вы больше не можете передавать произвольное количество аргументов функции, если это явно не ожидает этого. Если он ожидает 1 параметр определенного типа, вы должны указать ему 1 параметр ожидаемого типа, а не 2 или 3 параметра. –

+0

Но конструктор вызывает функцию 'super', чтобы передать данный объект базовому классу. Это неправильно? – mark

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'} 
 
    ] 
 
});

Смежные вопросы