Home > Blockchain >  error TS2322: Type 'keyof T' is not assignable to type 'T'. in typescript 4.4
error TS2322: Type 'keyof T' is not assignable to type 'T'. in typescript 4.4

Time:09-16

I have one function selectProperties to select the key value from some interface and get the error error TS2322: Type 'keyof T' is not assignable to type 'T'. after upgrading to typescript 4.4. typescript playground, anyone have better idea how I can walk around?

export interface QueryActioned {
  event: string;
  properties:string
}
export interface QueryStarted {
  event: number
  properties: number
}
export type QueryProps = Partial<(QueryActioned & QueryStarted)['properties']>;

const selectProperties = <T extends Partial<QueryProps>>(
  keys: (keyof T)[],
  properties: T
): T => {
  const defaultVal: T = {} as T;
  return (Object.keys(properties) as (keyof T)[])
    .filter((key) => keys.includes(key))
    .reduce(
      (acc, key) => ({
        ...acc,
        [key]: properties[key],
      }),
      defaultVal
    );
};

CodePudding user response:

Looks like that you are expecting reduce to return an object of type T, when it only accepts a default value that matches the type of the array value it is iterating over, and ultimately returns some combination of the values. Reduce will only end up returning a single value from the keys of T.

If you are selecting some of the keys of type T, you cannot have T as your return type. You are infact creating a Partial type based on the list of given keys.

You can return that by using forEach and mutating a return object.


export interface QueryActioned {
  event: string;
  properties:string
}
export interface QueryStarted {
  event: number
  properties: number
}
export type QueryProps = Partial<(QueryActioned & QueryStarted)['properties']>;

const selectProperties = <T extends Partial<QueryProps>>(
  keys: (keyof T)[],
  properties: T
) => {
  const defaultVal: Partial<T> = {};
  
  Object.keys(properties)
    .filter(key => keys.includes(key))
    .forEach(key => {defaultVal[key as keyof T] = properties[key]});

  return defaultVal
};


If you actually want to get the values from the selected keys on T, then you can use map instead...


export interface QueryActioned {
  event: string;
  properties:string
}
export interface QueryStarted {
  event: number
  properties: number
}
export type QueryProps = Partial<(QueryActioned & QueryStarted)['properties']>;

const selectProperties = <T extends Partial<QueryProps>>(
  keys: (keyof T)[],
  properties: T
): (T[keyof T])[] => {
  return Object.keys(properties)
    .filter(key => keys.includes(key))
    .map(key => properties[key]);
};


Either way, reduce will combine all the values in the keyof T array, and you specified your return type as T which would be where the error comes from.

  • Related