Nested generics in function definition in TypeScript

I am trying to make type handlers for decux actions based on an action type. For example, any action can be described as:

type ActionType<T extends string> = {
  type: T
};

For a specific action, you can:

type MyAction = ActionType<'hey' | 'there'>;

Now I would like to limit the function of the handler to allow only “hey” or “there” as a type. Finally, I expect something like this:

handleAction<MyAction>('hey');

where the definition of the handler function can be:

function handleAction<A extends ActionType<T>>(type: T){
...
}

But I have a typescript compiler error:


TS2304: Cannot find the name "T".


So, I need to change this definition of the handler function as follows:

function handleAction<A extends ActionType<T>, T extends string>(type: T){
...
}

This works, but it looks very ugly:

handleAction<MyAction, 'hey' | 'there'>('hey');

TS Playground

What is the best way to handle this?

+4
source share
3 answers

Edit

, type:

function handleAction<A extends ActionType<string>>(type: A ['type']) {
}

handleAction<MyAction>('hey');

2.8 ActionType (2.8 , 2018 , npm install -g typescript@next)

type ActionType<T extends string> = {
  type: T
};

type MyAction = ActionType<'hey' | 'there'>;


function handleAction<A extends ActionType<string>>(type: A extends ActionType<infer U> ? U : never) {
}

handleAction<MyAction>('hey');

. ActionType<infer U> : a extends ActionType U U. , U ActionType . U , . , .

+2

:

  • .

, ( ):

type FileAction = 'save' | 'read' | 'copy';
function doAction (a) {
}
declare function doAction<A extends string> (action: A): void;

doAction<FileAction>('save'); // good, as desired
doAction<FileAction>('xxx'); // error, as expected
  1. .type .

, .. .

type FileFile <T extends string> = {
  type: T;
}
type WordFile = FileFile<'why'|'you'|'no'|'work'>;

function doAction2 (a) {
}
declare function doAction2<F extends FileFile<string>> (action: F["type"]): void;

doAction2<WordFile>('no'); // good, as desired 
doAction2<WordFile>('xxx'); // error, as expected
+1

This clears up some things, but I'm not sure if this is what you are hoping for:

type ActionType<T extends string> = {
  type: T
};

type MyWord = 'hey' | 'there';
type MyAction = ActionType<MyWord>;

function handleAction<A extends ActionType<T>, T extends string>(type: T){
}

handleAction<MyAction, MyWord>('hey');
0
source

Source: https://habr.com/ru/post/1694443/


All Articles