3

I'm expecting that typescript will throw an error because I'm passing the wrong number of elements in EntryPoints, but it doesn't happen.

function createContext<T>(defaultValue: T): T[] {
  return [defaultValue]
}

interface EntryPoints {
  parentSelector: string;
}
interface SomeType {
  entryPoints: EntryPoints[];
}
const defaultData = {
  entryPoints: [{
    parentSelector: '',
    foo: 1 // <-- expecting error here
  }]
}
createContext<SomeType>(defaultData)

Same code without generic works as expected

function createContext<T>(defaultValue: T): T[] {
  return [defaultValue]
}

interface EntryPoints {
  parentSelector: string;
}
interface SomeType {
  entryPoints: EntryPoints[];
}
const defaultData: SomeType = {
  entryPoints: [{
    parentSelector: '',
    foo: 1 // <-- throwing error here
  }]
}
createContext(defaultData)

Playground

2 Answers 2

2

You're running into an object freshness issue so the additional key is allowed.

If you explicitly pass the object it will be properly typed checked:

function createContext<T>(defaultValue: T): T[] {
  return [defaultValue];
}

interface EntryPoints {
  parentSelector: string;
}

interface SomeType {
  entryPoints: EntryPoints[];
}

createContext<SomeType>({
  entryPoints: [
    {
      parentSelector: "",
      foo: 1 // <-- errors as expected here
    }
  ]
});

TypeScript Playground

Sign up to request clarification or add additional context in comments.

1 Comment

This isn't type widening. Type widening is a different thing.
1

What you're experiencing is the difference between

  1. type checking at the point of assigning a literal to a type and
  2. type checking at the point of assigning a variable to a type.

Consider that we have two types. One of them has one more property than the other has.

type Foo = {
  foo: string;
};

type FooBar = {
  foo: string;
  bar: string;
};

When assigning an object literal to a type, additional properties are NOT allowed.

// Object literal may only specify known properties,
// and 'bar' does not exist in type 'Foo'.
const foo: Foo = {
  foo: "foo",
  bar: "bar" // <---- bar is not allowed on Foo.
};

When assigning a variable to a type, additional properties are allowed.

const fooBar: FooBar = {
  foo: "foo",
  bar: "bar" // <---- bar is going to be allowed on Foo
};

const foo: Foo = fooBar; // <---- see, no error

It is okay to assign fooBar to foo because fooBar is a variable not an object literal and can therefore include unknown properties.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.