Typescript инициализация интерфейса

Мой уровень typescript - это "АБСОЛЮТНОЕ НАЧИНАНИЕ", но у меня хороший фон ООП. Я создаю с typescript ссылкой на внешнюю библиотеку t.ds, которая содержит следующий интерфейс:

interface ISimpleObject {
    foo: string;
    bar?: any;
}

Теперь, если я хочу вызвать метод с параметром IRequestConfig, как его создать? Я вижу различные варианты:

  • Создайте простую реализацию ISimpleObject. Мне не нравится этот подход, потому что он выглядит как шаблонный код для меня.
  • не инициализируйте объект (я боюсь, что это может сломать что-то...):

    var x :IsimpleObject; x.bar = 'xxx'; callMethod(x);

  • Вставьте pojo:

    var x :IsimpleObject = <IsimpleObject>{foo: 'yyy', bar:'xxx'};

    Мне не нравится этот подход либо потому, что он не обеспечивает безопасность типов...

Я думаю, это довольно тривиальный вопрос, и я пропускаю что-то тривиальное в typescript.

Ответ 1

Если у вас есть такой интерфейс, как:

interface ISimpleObject {
    foo: string;
    bar?: any;
}

Этот интерфейс используется только во время компиляции и для подсказки кода /intellisense. Интерфейсы используются для обеспечения строгого и безопасного типа использования объекта с определенной сигнатурой в согласованном порядке.

Если у вас есть функция с использованием interface, определенной выше:

function start(config: ISimpleObject):void {

}

Компиляция TypeScript завершится неудачно, если объект не имеет точной подписи интерфейса ISimpleObject.

Существует несколько допустимых методов вызова функции start:

// matches the interface as there is a foo property
start({foo: 'hello'});

// Type assertion -- intellisense will "know" that this is an ISimpleObject
// but it not necessary as shown above to assert the type
var x = <ISimpleObject> { foo: 'hello' }; 
start(x);

// the type was inferred by declaration of variable type
var x : ISimpleObject = { foo: 'hello' };  
start(x);

// the signature matches ... intellisense won't treat the variable x
// as anything but an object with a property of foo. 
var x = { foo: 'hello' };
start(x);    

// and a class option:
class Simple implements ISimpleObject {
    constructor (public foo: string, public bar?: any) {
       // automatically creates properties for foo and bar
    }
}
start(new Simple("hello"));

Всякий раз, когда подпись не соответствует, компиляция завершится неудачно:

// compile fail
var bad = { foobar: 'bad' };
start( bad );

// compile fail
var bad: ISimpleObject = { foobar: 'bad' };

// and so on.

Нет никакого "правильного" способа сделать это. Это вопрос выбора стиля. Если бы это был объект, который был сконструирован (а не просто передан непосредственно как параметр), я бы обычно объявлял тип:

var config: ISimpleObject = { foo: 'hello' };

Таким образом, выполнение кода /IntelliSense будет работать везде, где я использовал переменную config:

config.bar = { extra: '2014' };

В TypeScript нет "кастинга". Он называется утверждением типа и не должен нуждаться в описанных здесь случаях (я включил пример выше, где он может быть использован). Нет необходимости объявлять переменную Type, а затем использовать утверждение в этом случае (поскольку тип уже был известен).

Ответ 2

Typescript2:

const simpleObject = {} as ISimpleObject;

Ответ 3

  • Вы не можете создать экземпляр интерфейса, так как Typescript не переводит его в js. Вы можете проверить созданные js, и в нем ничего не увидите. Это просто для компиляции ошибок, типа безопасности и intelisense.

    interface IStackOverFlow
    {
       prop1 : string;
       prop2 : number;
    }
    
    public MyFunc(obj : IStackOverFlow)
    {
        // do stuff
    }
    
    var obj = {prop1: 'str', prop2: 3};
    MyFunc(obj); // ok
    
    var obj2 = {prop1: 'str'};
    MyFunc(obj); // error, you are missing prop2
    
    // getObj returns a "any" type but you can cast it to IStackOverFlow. 
    // This is just an example.
    var obj = <IStackOverFlow> getObj();