The concept in question relates to checking for excess properties and object literal freshness.
When does an object literal qualify as fresh, you may wonder?
An object literal is deemed fresh when TypeScript deduces its type without any explicit type assertions or variable assignments.
// using type assertion, this works
data: await createCategory({ id: 555, name: 'sdfsdf', parentId: 55 } as CreateCategoryDto)
In the first scenario where it's assigned to a variable, the freshness diminishes and there is no excess property checking.
const data = { id: 555, name: 'sdfsdf', parentId: 55 }; // assigned to a variable
data1: await createCategory(data)
However, if you directly pass the object literal to a function without assigning it first, TypeScript infers its type, making it fresh.
data: await createCategory({ id: 555, name: 'sdfsdf', parentId: 55 }) // fresh object
In such cases, excess property checking comes into play. When trying to assign a fresh object literal of type T to another type U, and T has additional properties not in U, TypeScript flags this as an error. This helps in catching misspellings.
As stated in the documentation:
[...] TypeScript considers this code potentially buggy. Object literals undergo excess property checking when assigned to variables, or passed as arguments. If an object literal contains properties not present in the "target type," an error will occur [...]
For instance:
var categoryDto: CreateCategoryDto = { id: 555, name: 'sdfsdf', parentId: 55 }
results in an error, while:
var categoryDto = { id: 555, name: 'sdfsdf', parentId: 55 }
var test: CreateCategoryDto = categoryDto
does not, showcasing the balance between usability and safety achieved through excess property checking with fresh object literals.