0

I have got these two interfaces in Typescript:

interface User {
  id: string
  name: string
}

and

interface Employee {
  position: string
  department: string
}

I would like to use like this:

{ // valid
  id: 'some-id',
  name: 'some-name',
}

{ // valid
  id: 'some-id',
  name: 'some-name',
  position: 'some-position',
  department: 'some-department',
}

but want it to fail when:

{ // invalid
  id: 'some-id',
  name: 'some-name',
  position: 'some-position',
}

{ // invalid
  id: 'some-id',
  name: 'some-name',
  department: 'some-department',
}

and my solution is:

type EmployeeAndUser = User & Employee;

type EmployeeUser = (User & { position: never, department: never }) | EmployeeAndUser;


const bilbo: EmployeeUser = {
    id: '123',
    name: 'bilbo',
    position: 'hobbit',
    department: 'shire'
}

Note this does not work the way I want because Typescript thinks it's User:

interface EmployeeUser extends User {
    position: string
    department: string
}

// this is valid
const bilbo: User | EmployeeUser = {
    id: '123',
    name: 'bilbo',
    position: 'asd',
}

My solution is a little verbose and I feel like there must be a better way.

How could it be better?

yusuf
  • 3,596
  • 5
  • 34
  • 39
  • `type EmployeeAndUser = (User & Employee) | User`? – jonrsharpe Jul 29 '20 at 20:29
  • I think `StrictUnion` should work here as well https://stackoverflow.com/questions/52677576/typescript-discriminated-union-allows-invalid-state/52678379#52678379 – Titian Cernicova-Dragomir Jul 29 '20 at 20:30
  • @TitianCernicova-Dragomir That looks nice but sadly does not cover it all ```Type '{ id: string; name: string; position: string; department: string; }' is not assignable to type 'Partial>'. Types of property 'id' are incompatible. Type 'string' is not assignable to type 'undefined'.``` happens when I provide all properties. – yusuf Jul 31 '20 at 10:01
  • 1
    @yusuf It seems to work: https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgKoGdrIN4FgBQyywAJgFzLphSgDmBRIcAthBVTSPfgL4GiRYiFAFFmABwA2AewCeEFHkLJx09MDDBpIdtToNkJCOLhQwrcLs7c++AmFniUqEFpABpCLPQAeACoAfMgAvMh+yBAAHpAgJOhhyAD8yADWXtIwCRQgEABu0ADc9o4oAMp6CGAubgASEJJOUP4ANGEAgpKSQaHhUTFxyHAgskkJAGTIAAqmmnCSPgBKEAjSUCQ+IpEIkgCuRj7V2p7e-h1drWmyGWEBrTn5UAFB2XmFxU7I5TSVhyD+3Z8KlVXNo6g1oC0bgR3qIJDJ5BA2rEMFhQiioMgJmIpHIFEU7PgHB9sfCFOiQoDvsC3AdMBiAD7IEm4xHIukBfHQ-ArEBUZAAI2Akn50gozIR5NCSiIRFIFAA5ABGABMAGZ5c0DIwWGxkPLBcLpBqtSo1Bo3AqABbSfmCsDG5REIwmMwWMAK9CW4BQCDygg8IA – Titian Cernicova-Dragomir Jul 31 '20 at 12:07
  • @TitianCernicova-Dragomir oh cool, earlier I tried `StrictUnion` rather than `StrictUnion` thanks. `StrictUnion` should be part of Util types – yusuf Jul 31 '20 at 13:25

0 Answers0