TypeScript: фильтрация необъявленных полей в объектном литерале, возвращаемом при типизированном обратном вызове

#typescript #types #callback #typescript-generics

Вопрос:

В TypeScript Playground следующий код гарантирует, что литерал объекта, переданный в createState , точно соответствует типу State :

 const Stator = {
  init: <S>() => {
    let s: S;
    return { 
      createState: (state: S): S => {
        s = state;
        return s;
      },
    };
  },
};

type State = {
    status: boolean;
}

const { createState } = Stator.init<State>();

const s = createState({ status: true, fieldIsNotInTypeDeclaration: true  });

// ERROR (as expected):  Object literal may only specify known properties,
// and 'fieldIsNotInTypeDeclaration' does not exist in type 'State'.
 

Однако, если я передаю обратный вызов, возвращающий литерал объекта, он проверяет только наличие всех полей типа State ; он не выдает ошибок, если включены дополнительные необъявленные поля:

 const Stator = {
  init: <S>() => {
    let s: S;
    return { 
      createState: (stateInitializer: () => S): S => {
        s = stateInitializer();
        return s;
      },
    };
  },
};

type State = {
    status: boolean;
}

const { createState } = Stator.init<State>();

const s1 = createState(() => ({ status: true, fieldIsNotInTypeDeclaration: true  }));
// No error. s1 now includes fieldIsNotInTypeDeclaration,
// despite not being in the State type.
// An error (expected) WILL be generated on attempting to access
// s1.fieldIsNotInTypeDeclaration:
// Property 'fieldIsNotInTypeDeclaration' does not exist
// on type 'State'.

const s2 = createState(() => ({ fieldIsNotInTypeDeclaration: true }));
// ERROR (expected): Property 'status' is missing in type
// '{ fieldIsNotInTypeDeclaration: boolean; }' but required in type 'State'.
 

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

 const s3 = createState((): State => ({ fieldIsNotInTypeDeclaration: true }));
// ERROR (expected): Object literal may only specify known properties,
// and 'fieldIsNotInTypeDeclaration' does not exist in type 'State'.
 

… но разве я не должен был этого делать? State был передан .init как универсальный, и createState то, что он вернул, уже имеет этот тип. Это подтверждается наведением курсора:

[Завис2

Я чего-то не понимаю?

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

1. Typescript применяет проверки избыточных свойств только при назначении литералов. Это их дизайнерский выбор. Поищите «проверки избыточных свойств машинописного текста», и вы найдете множество блогов об этом.