Ввод одной записи - PullRequest
       14

Ввод одной записи

1 голос
/ 09 апреля 2020

Я ищу определение типа TypeScript, которое описывает объект с одним свойством (имеющим любое значение).

Я знаю, что это индексные подписи, например,

type X = { [key: string]: any }

или альтернативно

type X = Record<string, any>

Однако это позволило бы объекту типа

const obj: X = {
  "a": 12,
  "b": "c"
}

Я ищу тип Y, который ограничивает obj единственным свойством, представляющим вид "RecordEntry" ", то есть

const obj: Y = {
  "a": 12
}

должно быть в порядке, но

const obj: Y = {
  "a": 12,
  "b": "c"
}

должно быть отклонено компилятором.

Возможно ли это?

Ответы [ 2 ]

0 голосов
/ 09 апреля 2020

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

type NotUnion<T, U = T> =
  T extends any ?
    [U] extends [T] ? T
    : never
  : never;

type SingleProperty<T extends {}> =
  keyof T extends NotUnion<keyof T> ? T
  : never;

const oneProperty = {
  a: 'a'
};
const onePropertyAgain: SingleProperty<typeof oneProperty> = oneProperty; // works

const twoProperties = {
  a: 'a',
  b: 'b'
};
const twoPropertiesAgain: SingleProperty<typeof twoProperties> = twoProperties; // compiler error

Вы можете сделать это немного приятнее, например:

function asSinglePropertyObject<T extends {}>(obj: SingleProperty<T>): SingleProperty<T> {
    return obj;
}

const oneProperty = asSinglePropertyObject({
    a: 1 // works
});

const twoProperties = asSinglePropertyObject({
    a: 1, // Type 'number' is not assignable to type 'never'
    b: 'a'
});
0 голосов
/ 09 апреля 2020

Звучит так, будто вы хотите просто

type RecordEntry<T> = Record<string, T>

Я не верю, что есть способ ограничиться только одним неопределенным типом. Семантика такой вещи также может сбивать с толку. Что если, например, у вас будет

class A {}

class B extends A {}

const obj: RecordEntry = { a: new A(), b: new B() };

Это будет ошибка компилятора?

...