Есть ли способ для TypeScript определить тип / this объекта?

#typescript

#typescript

Вопрос:

Следующий блок кода допустим в TypeScript, но не в Flow:

 var o = {
  x: 1,
  foo() { this.x = 'a'; }
};

o.foo();
  

Я могу вызвать сбой, если создам интерфейс для объекта:

 interface Obj {
    x: number;
    foo(this: Obj): void;
}

var o = {
  x: 1,
  foo(this: Obj) { this.x = 'a'; }
};

o.foo();
  

Есть ли опция компиляции TypeScript, чтобы заставить его работать как Flow? (т. Е. Не нужен интерфейс)

Комментарии:

1. Как у вас может быть параметр с именем this ?

2. Это единственный известный мне способ для TypeScript проверить тип ‘this’. Смотрите typescriptlang.org/docs/handbook/functions.html и выполните поиск по «этим параметрам»

3. Я бы не ожидал этого, внешний тип не был полностью определен в контексте этой функции. Но вам не обязательно определять интерфейс для этого, вы могли бы просто использовать обычный литерал типа объекта, добавляя свойства по мере их использования.

Ответ №1:

Он определяет тип для o в конечном счете, он просто не может этого сделать, пока o не будет полностью инициализирован. В этом примере это выдает желаемую ошибку только для второго назначения:

 var o = {
    x: 1,
    foo() { this.x = 'a'; }
};


o.x = 'b';
  

z.ts (7,1): ошибка TS2322: тип ‘string’ не может быть присвоен типу
‘число’.

Если вы попытаетесь быть явным и использовать typeof o for this type, результат будет неожиданным:

 var o = {
    x: 1,
    foo(this: typeof o) { this.x = 'a'; }
};


o.x = 'b';
  

Ошибок нет. Но почему? Для пояснения попробуйте скомпилировать тот же код с помощью —noImplicitAny:

z.ts (1,5): ошибка TS7022: ‘o’ неявно имеет тип ‘any’, потому что у него нет аннотации типа и на него прямо или косвенно ссылаются в его собственном инициализаторе.

Итак, я усугубил ситуацию, «прямо или косвенно сославшись на него в его собственном инициализаторе».

Кажется, единственный способ обойти это — определить foo функцию вне o объекта. К счастью, typescript поддерживает ссылки typeof o перед o определением:

 function foo(this: typeof o) { this.x = 'a'; }

var o = {
    x: 1,
    foo: foo
};

o.foo();
  

t.ts (1,32): ошибка TS2322: Тип ‘string’ не может быть присвоен типу
‘число’.