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>
)