sqllyw
sqllyw

Reputation: 73

How to make a key optional?

here is the code:

type TypeKey = 'A' | 'B' | 'C'
type Types = { [key in TypeKey] : string}

let myTypes : Types = {
    A : 'Apple',
    B : 'Banna'
}

this will have an error:

error: TS2741 [ERROR]: Property 'C' is missing in type '{ A: string; B: string; }' but required in type 'Types'.

How to make 'C' optional? thanks

Upvotes: 2

Views: 719

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074268

There may be a more elegant way, but you can do it by removing C from the type and then adding it back as an optional property:

type TypeKey = 'A' | 'B' | 'C'
// Remove C  vvvvv−−−−−−−−−−−−−−−−−−−−−−−−−−−−vvvvvv
type Types = Omit<{ [key in TypeKey] : string}, 'C'> & {C?: string}
// Add it back as an optional property −−−−−−−−−−−−−−^^^^^^^^^^^^^^

let myTypes : Types = {
    A : 'Apple',
    B : 'Banna'
}

Playground link


In a comment you've asked:

it works, but any better way? something like type TypeKey = 'A' | 'B' | 'C?'

Not as far as I know, but you can turn this on its head and define TypeKey in terms of Types rather than the other way around:

interface Types {
    A: string;
    B: string;
    C?: string;
}

type TypeKey = keyof Types;

let myTypes : Types = {
    A : 'Apple',
    B : 'Banna'
}

Playground link

Upvotes: 1

Pritam Kadam
Pritam Kadam

Reputation: 2527

You can write it in more generic fashion as below:

type TypeKey = 'A' | 'B' | 'C'
type Types = { [key in TypeKey]: string }

type Optional<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>

const myTypes: Optional<Types, 'C'> = {
  A: 'Apple',
  B: 'Banna'
}

Upvotes: 1

Related Questions