#typescript
#typescript
Вопрос:
Я пытаюсь установить тип переменной для свойства объекта, например, в приведенном ниже коде.
class Foo {
}
const obj = {
Foo,
};
const foo: Foo; // valid
const bar: obj.Foo; // Cannot find namespace 'obj'.
Это выдает ошибку Cannot find namespace 'obj'
. Есть ли способ установить тип переменной из свойства объекта, такой, чтобы foo
и bar
имели тип Foo
?
Ответ №1:
Сначала вам нужно получить тип obj
(используя typeof
), затем вы можете запросить Foo
тип его свойства:
declare const bar: (typeof obj)["Foo"];
Обратите внимание bar
constructor
, это не экземпляр.
Если вы ищете тип экземпляра, вы можете использовать InstanceType
утилиту:
declare const bar: InstanceType<(typeof obj)["Foo"]>;
Если вам нужно что-то более многоразовое:
type Obj = typeof obj;
type GetType<K extends keyof Obj> = InstanceType<Obj[K]>
const bar: GetType<'Foo'> = new obj.Foo();
Комментарии:
1. Это тоже могло бы сработать, но объявление
const bar: obj.Foo
(как я думаю, пользователь ожидает этого) было быdeclare const bar: InstanceType<(typeof obj)["Foo"]>
немного утомительным..2. Спасибо, просто добавлял
InstanceType
часть
Ответ №2:
Нет способа добавить тип к типу объекта. Самое близкое, что вы можете сделать, это использовать определение пространства имен. Пространство имен может содержать как переменные, так и типы. Пространство имен представлено как объект во время выполнения, поэтому оно может быть достаточно близко к тому, что вам нужно:
class Foo {
}
type _Foo = Foo;
const _Foo = Foo;
namespace obj {
export type Foo = _Foo;
export const Foo = _Foo; // to allow instantiation through obj.Foo
};
const foo: Foo; // valid
const bar: obj.Foo = new obj.Foo()
Комментарии:
1. Это работает, но есть ли какой-либо способ уменьшить размер этого? Я имею дело с 90 ~ классами
2. @SebastiaanYN Проблема в том, что вы используете одно и то же имя, поэтому внешнее имя будет псевдонимным, отсюда и необходимость во внешних
_
определениях. Также вам необходимо экспортировать как тип, так и значение (const
), чтобы класс работал точно так же, как раньше.. не уверен, как бы я уменьшил его, учитывая эти ограничения..
Ответ №3:
Вы можете назначить ее тип компактным способом следующим образом let bar: {Foo}
Обновить
Кроме того, поскольку я упомянул, что obj
это не пространство имен, поэтому я попробовал typeof
ключевое слово, так как нам нужно type
этого свойства. итак, вы можете попробовать это следующим образом
let bar: typeof obj.Foo;
Комментарии:
1. Это не отвечает на мой вопрос. Это просто говорит о том, что
bar
это объект со свойствомFoo
типаany
.2. @SebastiaanYN Поскольку
obj
это НЕ пространство имен (то естьclass
или anInterface
), было бы невозможно установить тип для свойства объекта. Также потому, чтоobj.value
синтаксис возвращает значение свойства, а не его тип3. @SebastiaanYN Я обновил ответ. Пожалуйста, проверьте это сейчас
4.
const bar: typeof obj.Foo = new obj.Foo();
дало быProperty 'prototype' is missing in type 'Foo' but required in type 'typeof Foo'.
5. @SebastiaanYN Я также получаю ошибку в TS, но если вы запустите код и увидите консоль, он создаст
Foo
объект и без ошибок в браузере (странно)