Ограничить использование обобщений Typescript для объекта

#javascript #typescript

#javascript #typescript

Вопрос:

Привет, ребята,

Я не настолько хорошо знаком с Typescript, но вот следующее, чего я хочу достичь, и в настоящее время я борюсь с:

Создайте объект с функцией createObject , как определено ниже. В качестве аргумента вы можете передать только параметр типа Object.

Он возвращает переданный в аргумент, но модифицированный свойством type и detail).

Это то, что я делал до сих пор.

 function createObject<T extends object>(options: T): T {
  if (!options.type) {
    if (options.showDetail) {
      options.type = 'text';
      options.detail = 'Some detail';
    } else {
      options.type = 'simple';
      options.detail = '';
    }
  }
  return options
}
  

Когда я выполняю свою функцию:

 const objectConfig = {
  name: 'Steven',
  age: 28,
}

const newObj = createObject(objectConfig);
  

Внутри функции createObject , options.type, options.showDetail, options.detail выделены красным. Typescript жалуется на:

[Строка 4] Свойство ‘type’ не существует для типа ‘T’.

[Строка 3] Свойство ‘showDetail’ не существует для типа ‘T’.

[Строка 5, 8] Свойство ‘detail’ не существует для типа ‘T’.

Кроме того, возвращая обобщенный параметр, вы возвращаете не измененный аргумент, а только входной аргумент. Т.е. я не получу подсказок Typescript о свойстве detail / type newObj .

Моя среда разработки просто дает мне подсказки по типу для свойства age и name. Как и ожидалось, поскольку я ошибочно возвращаю только входной аргумент.

Как я могу получить правильное решение typescript? Спасибо!

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

1. Ваш универсальный объект используется как тип, поэтому вы должны расширить тип, который имеет эти имена свойств: создайте этот интерфейс и расширьте его. Во-вторых, ваша objectConfig конструкция не соответствует типам для свойств, которые вы расширили. Some detail то, что это строка, вызовет проблемы при передаче age в виде числового типа.

Ответ №1:

Что ж… Проблема в том, что вы пишете TypeScript так, как будто это точно такой же JavaScript. Это не так, как это работает. Вот решение, которое просто работает, но вам нужно начать писать TypeScript, как вы пишете любой другой язык ООП1.

 interface OptionExtensions {
    type?: string,
    showDetail?: boolean,
    detail?: string
}

function createObject<T extends object>(options: T): T amp; OptionExtensions {
    let optionsExtended: T amp; OptionExtensions = options;
    if (!optionsExtended.type) {
        if (optionsExtended.showDetail) {
            optionsExtended.type = 'text';
            optionsExtended.detail = 'Some detail';
        } else {
            optionsExtended.type = 'simple';
            optionsExtended.detail = '';
        }
    }
    return optionsExtended;
}

let foo = createObject({
    name: "Steven",
    age: 28
});
  

Вот <a rel="noreferrer noopener nofollow" href="https:///www.typescriptlang.org/play/#src=interface OptionExtensions {
type?: string,
showDetail?: boolean,
detail?: string
}

function createObject(options: T): T & OptionExtensions {
let optionsExtended: T & OptionExtensions = options;
if (!optionsExtended.type) {
if (optionsExtended.showDetail) {
optionsExtended.type = ‘text’;
optionsExtended.detail = ‘Some detail’;
} else {
optionsExtended.type = ‘simple’;
optionsExtended.detail = »;
}
}
return optionsExtended;
}

let foo = createObject({
name: «Steven»,
age: 28
});» rel=»nofollow noreferrer»>демонстрационная версия. Вы можете проверить, foo обладает ли он всеми свойствами, которые вы ожидаете (написав «foo.» и просмотрев предложения).

Примечание 1: Под этим я подразумеваю, что, поскольку TypeScript имеет хороший вывод типов и ввод с уткой, это позволит вам заставить вещи работать без явного написания типов и создания интерфейсов, но не слишком долго. Подумайте, как бы вы писали вещи на языке ООП, а затем создавали соответствующие абстракции и модели.

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

1. Однако вы можете захотеть сохранить <T extends object> , иначе вас не заметят, если вы добавите, например, число или строку.