Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Type parameter 'T' has a circular default. scenario better #52492

Open
jpike88 opened this issue Jan 30, 2023 · 1 comment
Open

Handle Type parameter 'T' has a circular default. scenario better #52492

jpike88 opened this issue Jan 30, 2023 · 1 comment

Comments

@jpike88
Copy link

jpike88 commented Jan 30, 2023

Suggestion

I've done a lot of research about what I want, and nothing out there seems to reference it. So either what I want is very niche or not possible yet.

I have the following type defined:

type TableUpdateFn<T = any> = {
	apiCall: (
		query: Query,
		progressCallback?: (progressType, loaded, total) => void,
		isCancellable?: boolean
	) => Promise<{ rows: T[]; count: number }>;
	transformRows?: (
		rows: T[],
		customTableComponent: CustomTableComponent
	) => Promise<void>;
	selected?: (sourceObj: T) => boolean;
	warning?: (sourceObj: T) => boolean;
};

The most important thing about this type is the type of the rows property (a single item, not the array type applied to it) returned by the apiCall promise. This type should determine how other functions are on the rest of the type.

Using generics seems like the most reasonable way to handle this, but unfortunately I'm stuck with either manually specifying the generic each time I use this type (which defeats the purpose of relying on apiCall for the type), or just defaulting to any.

What I would like to be able to do is something like this, which means the whole object matching this type will inherit the type of rows[0]:

type TableUpdateFn<
	T = Awaited<ReturnType<this['apiCall']>>['rows'][0]
> = {
	apiCall: (
		query: Query,
		progressCallback?: (progressType, loaded, total) => void,
		isCancellable?: boolean
	) => Promise<{ rows: T[]; count: number }>;
	transformRows?: (
		rows: T[],
		customTableComponent: CustomTableComponent
	) => Promise<void>;
	selected?: (sourceObj: T) => boolean;
	warning?: (sourceObj: T) => boolean;
};

🔍 Search Terms

interface self-reference recursion

@jpike88
Copy link
Author

jpike88 commented Jan 30, 2023

Another notes:

Even though typescript complains about the second example in my post above, my codebase lit up with some errors which actually helped me.

The below code snippet for example was invalid but got flagged, which again is a good thing:

const updateFn: TableUpdateFn<X> = {
     apiCall:... // { rows: Y[], count: number},
     selected: (someVar) =>...// do something with someVar, which would be of type X,
...
}

Only problem is that the selected method in the above method errored because someVar became type unknown instead of the type I wanted (type Y)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant