Конкретный тип объекта нельзя ввести как запись?

#typescript

Вопрос:

Я хочу определить интерфейс для общей строки таблицы, в основном это любой объект, ограниченный значениями атрибутов в качестве примитивных типов.

Но когда я пытаюсь назначить объекту определенного типа строку, это не удается. Почему? И как заставить это работать? Я хочу обеспечить, чтобы строки могли быть только объектами с примитивными значениями атрибутов.

игровая площадка

 // Table row
export type Row = Record<string, string | number | undefined>

// User
interface User { name: string }
const jim: User = { name: 'Jim' }
const row: Row = jim // <== Error
 

Ошибка

 Type 'User' is not assignable to type 'Row'.
  Index signature for type 'string' is missing in type 'User'.
 

Ответ №1:

Интерфейсы могут быть расширены. Без ограничения типа индекса объект, расширяющий пользователя, который может храниться в переменной, введенной пользователем, может иметь другие свойства.

 // User
interface User { name: string }
interface FooUser extends User { foo(): void; }
const jim: FooUser = { name: 'Jim', foo() {} }
const jimAsUser: User = jim;
const row: Row = jim;  // fails as it should:
                       // foo is not a string, number, or undefined!
 

Обратите внимание , что если вы используете type вместо interface этого, это безопаснее: дополнительные свойства в подинтерфейсах не ожидаются. Тем не менее, Машинопись позволяет это, хотя и не должна. type и interface есть некоторые тонкие детали, на которые ссылается руководство по машинописи (хотя и не вдаваясь в этот конкретный случай).

 // UserAsType
type UserAsType = { name: string };
const jimAsType: UserAsType = { name: 'Jim' }
const jimAsTypeFromFooUser: UserAsType = jim;  // this *should* fail
const row2: Row = jimAsType
 

Ссылка на игровую площадку