jjjjjjjjjjjjjjjjjjjj
jjjjjjjjjjjjjjjjjjjj

Reputation: 3118

Can "no unknown properties" be enforced using function types?

When defining a function's return type we'll receive a type error if we include a property in the returned object that is not present in the return type, stating that object literals may only specify known properties.

// Type '{ status: string; bar: string; }' is not assignable to type '{ status: string; }'.
// Object literal may only specify known properties, and 'bar' does not exist in type '{ status: string; }'.(2322)
const foo = function(): {status: string} {
    return {
        status: '200 OK',
        bar: 'baz', // Problem
    }
}

When defining a function type, we'll receive a type error when omitting a known property from the returned object, stating that the known property is missing:

// Type '() => { baz: string; }' is not assignable to type '() => { status: string; }'.
// Property 'status' is missing in type '{ bar: string; }' but required in type '{ status: string; }'.(2322)
const foo: () => {status: string} = function () {
    return {
        // status: '200 OK'
        bar: 'baz',
    }
}

However, again when defining a function type–which correctly raises a type error for missing properties–a type error will not be raised when returning an object containing extra properties:

const foo: () => {status: string} = function () {
    return {
        status: '200 OK',
        bar: 'baz', // No problem
    }
}

  1. Why does the final example not raise a type error?
  2. Is there any way to enforce "no extra properties" on the return object using a function type?

See in playground

Upvotes: 3

Views: 222

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074385

  1. Why does the final example not raise a type error?

Because the function doesn't declare a return type, so all the type information about the function is inferred from the function's definition. That means its return type is inferred from the object literal ({status: string, bar: string}). That return type is effectively a subclass of the return type of the function the variable is expecting, to the assignment is valid.

  1. Is there any way to enforce "no extra properties" on the return object using a function type?

Type the function itself, like the first block in your question, so that TypeScript knows the function isn't allowed to add bar. TypeScript will infer the type of the variable from the function.

If you want to type the variable explicitly rather than allowing Typescript to infer its type, you could do this (playground link):

const foo2: () => {status: string} = function (): ReturnType<typeof foo2> {
    return {
        status: '200 OK',
        bar: 'baz',
    };
};

but your first code block is simpler.

Upvotes: 3

Related Questions