enum Channel {
GITHUG = 'github',
GITLAB = 'gitlab',
}
interface Github {}
interface Gitlab {}
function foo (a, b) {}
The first parameter a is an enum (Channel) value
If parameter a is github, then the type of b is GitHub
If parameter a is gitlab, then the type of b is Gitlab
How to define the type of function foo?
enum Channel {
GITHUG = 'github',
GITLAB = 'gitlab',
}
interface Github {}
interface Gitlab {}
function foo (a, b) {}
The first parameter a is an enum (Channel) value
If parameter a is github, then the type of b is GitHub
If parameter a is gitlab, then the type of b is Gitlab
How to define the type of function foo?
Share Improve this question edited May 21, 2021 at 11:18 loveyunk asked May 21, 2021 at 10:31 loveyunkloveyunk 3783 silver badges13 bronze badges 1- typescriptlang/docs/handbook/2/…? – jonrsharpe Commented May 21, 2021 at 10:33
4 Answers
Reset to default 4Here you have some alternative ways:
enum Channel {
GITHUB = 'github',
GITLAB = 'gitlab',
}
interface Github {
type: 'Github'
}
interface Gitlab {
type: 'Gitlab'
}
/**
* First approach
*/
type Params = [Channel.GITHUB, Github] | [Channel.GITLAB, Gitlab]
function foo(...args: Params) {
if (args[0] === Channel.GITHUB) {
const x = args[1] // Github
}
}
type Overloading =
& ((a: Channel.GITHUB, b: Github) => void)
& ((a: Channel.GITLAB, b: Gitlab) => void)
/**
* Second approach
*/
const foo2: Overloading = (a: Channel, b: Github | Gitlab) => null as any
const result = foo2(Channel.GITHUB, { type: 'Github' }) // ok
/**
* Third approach
*/
function foo3(a: Channel.GITLAB, b: Gitlab): void
function foo3(a: Channel.GITHUB, b: Github): void
function foo3(a: Channel, b: Github | Gitlab) {
}
foo3(Channel.GITLAB, { type: 'Gitlab' }) // ok
Playground
Use conditional types technique. Look at example below or go to online playground in order to test in action (thanks for help to Joonas)
enum Channel {
GITHUG = 'github',
GITLAB = 'gitlab',
}
interface Github {
_foo: number
}
interface Gitlab {
_bar: number
}
type ParamType<C> = C extends Channel.GITHUG ? Github : Gitlab;
function foo<C extends Channel>(a: C, b: ParamType<C>): void {}
foo(Channel.GITLAB, { _foo: 1 }); // error
foo(Channel.GITLAB, { _bar: 1 }); // success
Please, let me know if it works or not )
Explain look at the code ments:
enum Channel {
GITHUG = 'github',
GITLAB = 'gitlab',
}
interface Github {}
interface Gitlab {}
// Map enum value and type
interface Foo {
github: Github
gitlab: Gitlab
}
// `${Channel}` => 'github' | 'gitlab'
// Get the type K of a through the passed parameter
// if K is `github`, Foo[K] is Github
// if k is `gitlab`, Foo[K] is Gitlab
function foo<K extends `${Channel}`>(a: K, b: Foo[K]) {}
Playground
I had a very similar problem, in my case, the second parameter type es from an interface:
interface ArgTypes { [id: string]: any }
interface ChannelArgs extends ArgTypes{
github: {
hubhub: number
},
gitlab: {
lablab: number
},
...
}
type Arg<Args extends ArgTypes, Id extends keyof Args> = Args[Id]
My foo
function has to work with all types implementing the interface, so it is generic itself:
foo<ChannelArgs>('github', {hubhub: 12})
Turns out, declaration of a generic type and an inferred type does not mix, but it is possible to put them in different brackets:
type Foo<Args extends ArgTypes> = <Id extends keyof Args>(
id: Id,
arg: Arg<Args, Id>
) => void
const gitFoo: Foo<ChannelArgs> = function(a,b): void {}
gitFoo('github', {hubhub: 12}) // no error
gitFoo('github', {lablab: 12}) // error
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745375008a4624958.html
评论列表(0条)