Установка типа переменной из свойства объекта

#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 или an Interface ), было бы невозможно установить тип для свойства объекта. Также потому, что 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 объект и без ошибок в браузере (странно)