简体   繁体   中英

Dynamic Key name with in the defined list for a Map in typescript

I am trying to define the type in typescript.. that should accept at least one key-value (within the defined list). If the data has at least one defined key among the list, remaining should be optional.

Is there any way we can do that in typescript.

type values = 'a' | 'b' | 'c' | 'd';
type data<T extends string, K> = Record<T, K>;

// current output:
const d:data<values, string> = {
  'a': 'sample text',
  'b': 'b sample text',
  'c': 'c sample text'
};

// Expecting output
const d:data<values, string> = {
  'a': 'sample text'
}

In the above example, d expects every key in the values . I did try partial it is making all values are optional.

my intention is when the incoming data should have at least one key from the values .

Note: Values are so dynamic or have a longer list.

You can do this by intersecting a mapped type to require each property individually with Partial<T>

type AtLeastOne<T> = {
    [K in keyof T]: {
        [K2 in K]: T[K]
    }
}[keyof T] & Partial<T>

How it works:

  1. Loop over all the keys in the provided record, and set the type in the resulting record to be an object with just that key { [K in keyof T] ... }
  2. Get the union of all elements in the mapped type [keyof T]
  3. Intersect the union with Partial<T> to require any other provided properties to be the correct type

Demo: Playground

type AtLeastOne<T> = {
    [K in keyof T]: {
        [K2 in K]: T[K]
    }
}[keyof T] & Partial<T>

type Data<K extends string, T> = AtLeastOne<Record<K, T>>

type Keys = 'a' | 'b' | 'c' | 'd'

type Result = Data<Keys, string>

const x: Data<Keys, string> = {
    a: '' // ok
}

const y: Data<Keys, string> = {} // error

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