简体   繁体   中英

how to define an object with optional props from an union type in TypeScript

I want to use mapped types to define the type of the following type:

Examples:

    const k0: Keyed = {};    // ok, empty
    const k1: Keyed = { year: 1, month: 2, week: 3 };    // ok
    const k2: Keyed = { year: 1 };    // ok, partial
    const k3: Keyed = { hour: 1 };    // wrong! hour is not in 'year' | 'month' | 'week'
    const k4: Keyed = { year: undefined }; // wrong, I want a number, not an undefined

I tried with the following:

    type Keyed = {
        [key in 'year' | 'month' | 'week']: number;
    };

but const k2: Keyed = { year: 1 } fails with the error Type '{ year: number; }' is missing the following properties from type 'Keyed': month, week Type '{ year: number; }' is missing the following properties from type 'Keyed': month, week

Then I tried with the following to allow Keyed variables that don't have every key

    type Keyed = {
        [key in 'year' | 'month' | 'week']?: number;
    };

But then the following const d: Keyed = { year: undefined }; is reported ok, with all the correspondent 'xxx may be undefined` messages

I want to define that the keys of Keyed must be one of 'year' | 'month' | 'week' 'year' | 'month' | 'week' 'year' | 'month' | 'week' , without neccesarily having all the properties defined, and that the value should be a number (not null nor undefined).

It seems like a really simple case but I can't find the way to achieve it.


I noticed that a similar problem arises with explicit properties. If I have:

  type T = {
    name?: string
  }

All these are valid:

  const t1: T = {name: 'sas'}
  const t2: T = {name: undefined}
  const t3: T = {}

I'd like the 'name' property to be optional (that is, it can be missing), but if it is present I want it to be a string, not undefined.


for reference: the solution wa to set the exactOptionalPropertyTypes option in the tsconfig.json file

turn on exactOptionalPropertyTypes in your tsconfig.json (you allow {} type, I think it's ok)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM