Skip to content

Destructured parameter should not enforce presence / non-nullability from type annotation on a property that's default-initialized #7678

Closed
@Arnavion

Description

@Arnavion

TypeScript Version:

55cbdc9 (current master)

Code

type Props = { propA: number, propB: string, propC: number };

var p: Props = { propC: 0 }; // Not a Props, missing propA and propB. Error, as expected
var q: Props = { propA: 6, propB: "b", propC: 0 }; // Ok, is a Props
var r = { propA: 6, propB: "b", propC: 0 }; // Not annotated, but is a Props
var s = { propA : 6, propC: 0 }; // Not a Props, missing propB. Not annotated, so not an error
var t = { propC: "c" }; // Not a Props, propC is the wrong type. Not annotated, so not an error

// No type annotation on parameter
function Component({ propA = 5, propB = "a", propC }) {
    console.log(propA, propB, propC); // propC is any, undesirable
}

Component(q); // No error, expected
Component({ propC: 0 }); // No error, expected
Component(r); // No error, expected
Component(s); // No error, expected
Component(t); // Error, expected

// Type annotation on parameter
function Component2({ propA = 5, propB = "a", propC }: Props) {
    console.log(propA, propB, propC); // propC is number, desirable
}

Component2(q); // No error, expected
Component2({ propC: 0 }); // Error, propA and propB are missing
Component2(r); // No error, expected
Component2(s); // Error, propB is missing
Component2(t); // Error, expected
tsc -t es5 ./foo.ts

Expected behavior:

Component2({ propC: 0 }) and Component2(s) compile even though their parameters don't have propA and propB from Props, because Component2 default-initializes those parameters.

Actual behavior:

foo.ts(26,12): error TS2345: Argument of type '{ propC: number; }' is not assignable to parameter of type '{ propA: number; propB: string; propC: number; }'.
  Property 'propA' is missing in type '{ propC: number; }'.
foo.ts(28,12): error TS2345: Argument of type '{ propA: number; propC: number; }' is not assignable to parameter of type '{ propA: number; propB: string; propC: number; }'.
  Property 'propB' is missing in type '{ propA: number; propC: number; }'.

plus errors about p and Component2(t) which are expected.


The reason to add the annotation on Component2 is to get type information for the non-default-initialized property propC.

Is there any downside to allowing Component2({ propC: 0 }) and Component2(s) ? Component2(t) should of course still not be allowed. s and { propC: 0 } should still not be considered to be Props for the purpose of type inference.

Otherwise the user has to make a new type for each such function based on what's default-initialized and what isn't, like type PropsForComponentFunction = { propA?: number, propB?: string, propC: number }, and make sure the types match with the original Props. (Or inline the whole type declaration into Component2 but that has the same drawback.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    SuggestionAn idea for TypeScriptToo ComplexAn issue which adding support for may be too complex for the value it adds

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions