Home > other >  Typescript Same generic in two interface properties, require same type
Typescript Same generic in two interface properties, require same type

Time:07-27

I'm defining the following interface:

interface I<T>{
 foo: T
 arr: T[]
}

Then I create an identity function using the interface:

const fn = <T>({foo, arr}: I<T>) => ({foo, arr})

Later, when I call the function, I was expecting typescript would flag this as an error:

const res = fn({
 foo: {a: 'a', b: 'b'},
 arr: [{c: 'c'}],
}) // {a: string, b:string} !== {c:string}

But it does not.

So my question is, how can I assert that the types of foo and each element of arr are required to be of exactly the same type? meaning that I would only be able to call fn like this:

const res = fn({
 foo: {a: 'a', b: 'b'},
 arr: [{a: 'hello', b: 'world'}],
}) // T = {a: string, b: string}

Thanks!

CodePudding user response:

try this , using only one generic in func will union type

interface I<T, U> {
  foo: T
  arr: U[]
}

const fn = <T, U extends T>({ foo, arr }: I<T, U>) => ({
  foo,
  arr,
})

const res = fn({
  foo: { a: 'a', b: 'b' },
  arr: [{ c: 'c' }],
}) // error

const res2 = fn({
  foo: { a: 'a', b: 'b' },
  arr: [{ a: 'a1', b: 'b', c: 1 }],
}) // won't error , but ok, since type is safe

CodePudding user response:

Here is a way to make it so that the type of arr must match what is specified in foo:

interface I<T, U extends T=T> {
    foo: T
    arr: U[]
}

const fn = <T, U extends T=T>({ foo, arr }: I<T, U>) => ({ foo, arr })

const res = fn({
    foo: { a: 'a', b: 'b' },
    arr: [{ c: 'c' }], //now flagged as error
})

Other than using fn as shown above (inferring all the types automatically), you can also specify a parameter like fn<SomeType> which will restrict the type of foo that can be passed. (Here, it's ok to specify only one template parameter, because when U is not specified explicitly, U = T, so it will give fn<SomeType,SomeType>)

  • Related