analytics-next icon indicating copy to clipboard operation
analytics-next copied to clipboard

Argument of type `Record<string, string>` is not assignable to parameter of type `Traits | Callback | null | undefined`

Open zygopleural opened this issue 2 years ago • 3 comments

Breaking change introduced

I have a breaking change trying to upgrade 1.41.0 -> 1.42.1

Expected

I should be able to pass any Record<string, string | number | JSONValue> as traits into the identify call.

Actual

I can only only pass Record<string, JSONValue>

Culprit

Looks like here was a breaking change in @segment/[email protected]

I believe https://github.com/segmentio/analytics-next/pull/561 is the culprit, specifically these changes

zygopleural avatar Aug 10 '22 09:08 zygopleural

@zygopleuralI Thanks for taking out an issue. I wasn't able to reproduce --

// This works
const traits: Record<string, string> =  {name: "hello"}
analyics.identify("foo", traits) 

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgQQHYEMA2BPGwDGAzgEJQQDuhAplADQoY55FwC+cAZmSHAOQAC1AOYgqqGAHp0jXAUIBaVFQAeMXgChNm-BFSF4MKOmAxCALjgAlKjqgATADz6owVEPrPXQgHxwAvHCIGKIWAEQAFlSYmBChrADc6gAUCOzohAxYskQAlAB0wHZieBzYSaEcELH0hsamOVpAA

FYI, the definition of JSONValue already contains string | number, so Record<string, JSONValue> is the same as Record<string, string | number | JSONValue>

// This works
const traits: Record<string, JSONValue | string | number> =  {name: "hello"};
analytics.identify("foo", traits)

Is there a more advanced type you're having problems with?

silesky avatar Aug 10 '22 15:08 silesky

const { id, picture, signInMethod, ...traits } = user
identify(id, traits)

I'm seeing

Screenshot 2022-08-10 at 16 41 02

Even if I do

const t = traits as Traits
Screenshot 2022-08-10 at 16 42 33

zygopleural avatar Aug 10 '22 15:08 zygopleural

@zygopleural Thank you for the detail, that's an interesting one, and will be a problem if anyone attempts to coerce an object created with that pattern to a Record type. For now, you can fix by casting traits to "object" or by creating a UserTraits type like this:

type UserTraits = {
  name: string
  age: string
}
const { id, picture, signInMethod, ...traits } = user
identify(id, traits as UserTraits)

silesky avatar Aug 10 '22 16:08 silesky

@zygopleural fixed in ~~1.42.2~~ 1.42.3

silesky avatar Aug 10 '22 23:08 silesky

FYI @zygopleural there is an open Typescript issue about this scenario / bug: https://github.com/microsoft/TypeScript/issues/48014

silesky avatar Aug 11 '22 02:08 silesky

FYI @zygopleural there is an open Typescript issue about this scenario / bug: https://github.com/microsoft/TypeScript/issues/48014

Ah nice find!

zygopleural avatar Aug 11 '22 06:08 zygopleural