это конструктор для буквально типизированных объектов. Во время выполнения это просто добавление свойств к объекту, но определение позволяет TypeScript отслеживать буквальный ключ и типы значений. Во всяком случае, надеюсь, что это полезно. Удачи!

лятор Typescript выведет строковый литерал для констант:

const a = 'abc';
const b: 'abc' = a; // okay, a is of type 'abc' rather than string

Тем не менее, для свойств, тип выводится какstring.

const x = {
    y: 'def',
};

const z: { y: 'def' } = x; // error because x.y is of type string

В этом примере, как я могу заставить компилятор сделать вывод, чтоx имеет тип{ y: 'def' } без написания аннотации типа дляx?

Редактировать: Там открытвопрос Запрос поддержки для этой функции. Один из предложенных способов - использовать такой синтаксис:

const x = new class {
    readonly y: 'def';
};

const z: { readonly y: 'def' } = x; // Works

Попробуйте это на детской площадкеВот.

Изменить 2: Там даже открытPR это решило бы эту проблему. Отключение расширения типов - популярный запрос.

 artem02 дек. 2017 г., 17:27
Вы можете сказать компилятору, что что-то имеет определенный тип сутверждение типа: const x = { y: 'def' as 'def', };

Ответы на вопрос(2)

Решение Вопроса

const Ключевое слово для свойств. Поскольку невозможно гарантировать, что свойства не будут видоизменяться TS не может принимать константный строковый литерал, он должен предполагать более общийstring.

Попробуйте заменить первыйconst в вашем примере сlet и в этом месте тоже TS будет предполагатьstring и нет'abc':

let a = 'abc';
const b: 'abc' = a; 

TS Playground ссылка для этого кода

Собирается показать ошибку дляb Msgstr "Тип строки не может быть присвоен типу" abc ".

Поскольку TS не может вывести неизменность из языковой функции, как вы делаете в вашемconst В примере с переменными единственный способ сообщить ему, что свойство obejct является неизменным, - через явную аннотацию типа, что означает, что ответ на ваш вопрос отрицательный.

Да, это проблема (Microsoft / Машинопись # 10195) раздражает людей, которые любят его хранитьDRY, Как упоминает @artem, вы можете сделать это:

const x = {
    y: 'def' as 'def'  // WET  
};
const z: { y: 'def' } = x; // okay

но это требует от вас упомянуть'def' дважды; один раз как значение и один раз как тип. МашинописьМожно быть вынужденным выводить более узкие типы для параметров типа в общих классах или функциях, но не внутри литералов объекта.

Тем не менее, если вы хотите жить с пользовательской библиотекой и немного больше накладных расходов, вы можете сделать это:

const x = LitObj.of('y', 'def').build(); // DRY
const z: { y: 'def' } = x; // okay

гдеLitObj определяется так (желательно в своем собственном модуле где-то далеко от вашего кода):

type Lit = string | number | boolean | undefined | null | {};
class LitObj<T> {
  obj = {} as T;
  private constructor() {
  }
  and<K extends string, V extends Lit>(k: K, v: V): LitObj<T & Record<K, V>> {
    var that = this as any;
    that.obj[k] = v;
    return that;
  }
  build(): {[K in keyof T]: T[K]} {
    return this.obj;
  }
  static of<K extends string, V extends Lit>(k: K, v: V): LitObj<Record<K,V>> {
    return new LitObj<{}>().and(k,v);
  }
}

Идея в том, чтоLitObj это конструктор для буквально типизированных объектов. Во время выполнения это просто добавление свойств к объекту, но определение позволяет TypeScript отслеживать буквальный ключ и типы значений. Во всяком случае, надеюсь, что это полезно. Удачи!

Ваш ответ на вопрос