简体   繁体   中英

why typescript behaves differently when using the type directly vs using generics with extends?

I dont understand why the code behaves differently when using generics.
The topic is based on the answer for How to create a relation between parameters of a function?

interface Data {
  a: number,
  b: { x: number, y: number}
}

type GetKeyValueTuples<T> = { [Key in keyof T]: [Key, T[Key]] }[keyof T];

function getChangedDataByProperty<T extends Data>(
  ...[data, changedProp, newPropValue]: [T, ...GetKeyValueTuples<T>]
) {
  if (changedProp === "b") {
    changedProp
    return {
      ...data,
      b: {
        // why this has number, a, b types?
        x: newPropValue.x,
        y: newPropValue.y,
      }
    }
  } else {
    return {
      ...data,
      x: newPropValue
    }
  }
}

// why this behaves differently than the abvove function?
function getChangedDataByProperty2(
  ...[data, changedProp, newPropValue]: [Data, ...GetKeyValueTuples<Data>]
) {
  if (changedProp === "b") {
    changedProp
    return {
      ...data,
      b: {
        x: newPropValue.x,
        y: newPropValue.y,
      }
    }
  } else {
    return {
      ...data,
      x: newPropValue
    }
  }
}

The ts playground

The getChangedDataByProperty2() function's rest parameter is of a discriminated union type, and since TypeScript 4.6 we've been able to destructure such discriminated unions into separate parameters to get the narrowing behavior you're seeing, where a check of the discriminant changedProp narrows the type of newPropValue .

On the other hand, getChangedDataByProperty() 's rest parameter is of a generic type which is ultimately constrained to the same discriminated union type. For whatever reason, TypeScript does not consider a generic type to be an acceptable discriminant for a discriminated union . There is an issue filed at microsoft/TypeScript#50652 about this, but it's currently marked as "needs investigation" so there's no official word on whether this is a bug, a design limitation, or can be interpreted as a feature request. It's also on the backlog, which means that such official word might not be forthcoming.

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