Typescript - Проверьте, что объект имеет все свойства интерфейса - PullRequest
1 голос
/ 14 мая 2019

Скажем, у меня есть некоторый интерфейс:

export interface MyDocument {
    id: string,
    collection: string[];
}

Затем я создаю новый (хорошо приведенный существующий к этому типу):

const workingDocument = <MyDocument>document;

И, наконец,, У меня есть блок if, чтобы проверить, действительно ли он содержит все, что я указал в этом интерфейсе:

if (!workingDocument.id) {
   throw new Error("Document missing `id`");
} else if (!workingDocument.collection) {
   throw new Error("Document missing `collection` array");
}

Однако мне не нравится это, так как оператор if может расти вечно и не очень хорошоподдерживать.

Есть ли лучший способ?

Спасибо.

Ответы [ 2 ]

1 голос
/ 14 мая 2019

Оригинальный ответ

Если я правильно понимаю, вы запрашиваете проверку во время выполнения, чтобы объект включал все свойства, которые определяет интерфейс. Это невозможно с самим интерфейсом, потому что информация о типе, связанная с интерфейсом, не делает его во время выполнения; другими словами, интерфейс только полезен, когда мы запускаем компилятор TypeScript.

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

export interface MyDocument {
    id: string,
    collection: string[];
}

const isMyDocument = (input: any): input is MyDocument => {

    const schema: Record<keyof MyDocument, string> = {
        id: 'string',
        collection: 'array'
    };

    const missingProperties = Object.keys(schema)
        .filter(key => input[key] === undefined)
        .map(key => key as keyof MyDocument)
        .map(key => new Error(`Document is missing ${key} ${schema[key]}`));

    // throw the errors if you choose

    return missingProperties.length === 0;
}

const obj = {};

if (isMyDocument(obj)) {
  // the compiler now knows that obj has all of its properties
  obj.collection;
} 

Вот код выше на игровой площадке TypeScript .

Ответ на вопрос в комментариях

Вот как вы можете использовать оператор ... для расширения схемы.

interface ParentDocument { 
    id: string,
    collection: [],
}

interface ChildDocument extends ParentDocument { 
    name: string;
}

const schemaParent: Record<keyof ParentDocument, string> = {
    id: 'string',
    collection: 'array'
};

const schemaChild: Record<keyof ChildDocument, string> = {
    name: 'string',
    ...schemaParent,
};
1 голос
/ 14 мая 2019

Если вы создаете / используете этот тип документа для внутреннего использования, вы можете использовать типы / интерфейсы для утверждения их типов - для себя - без необходимости приведения.

Однако, если документы находятся за пределами вашего приложения для машинописного текста, вам нужно привести к какой-либо форме ручной проверки / проверки типов (то, чего вы хотите избежать).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...