My goal is to have different type for different parameter type
Here is my code
import React from "react";
type Response<T> = {
data: T;
description: string;
date: string;
};
type Data = {
title: string;
name: string;
};
type DataWidthLabel = Data & { labels: string };
type Endpoint = "endpoint_1" | "endpoint_2";
type FnResponse<T> =
T extends "endpoint_1" ? Response<Data> :
T extends "endpoint_2" ? Response<DataWidthLabel> : never;
type Props = {
endpoint: Endpoint;
children: (data: Response<Data> | Response<DataWidthLabel>) => void;
};
function queryFunction<T extends Endpoint>(endpoint: T): FnResponse<T> {
if (endpoint === "endpoint_1") {
return {
data: {
title: "title",
name: "name"
},
description: "description",
date: "date"
} as FnResponse<T>;
}
return {
data: {
title: "title",
name: "name",
labels: "labels"
},
description: "description",
date: "date"
} as FnResponse<T>;
}
const DataComp: React.FC<Props> = ({ endpoint, children }) => {
// queryFunction takes a type argument (<myType>) to type the data response
const data = queryFunction(endpoint);
return (
<div>
{children(data)}
<div>
<p>{data.description}</p>
<p>{data.date}</p>
</div>
</div>
);
};
const ParentComp1 = () => (
<DataComp endpoint="endpoint_1">
{(data) => {
return data.data.name;
}}
</DataComp>
);
const ParentComp2 = () => (
<DataComp endpoint="endpoint_2">
{(data) => {
return data.data.labels;
}}
</DataComp>
);
export default function App() {
return (
<div className="App">
<ParentComp1 />
-----
<ParentComp2 />
</div>
);
}
I'm not able to fix error for the case return data.data.labels;
CodePudding user response:
If you make Props
generic, then you can say that the parameter in data
must be the FnResponse
of the endpoint
field:
type Props<E extends Endpoint> = {
endpoint: E;
children: (data: FnResponse<E>) => void;
};
Also, you could change FnResponse
to a lookup table instead:
type FnResponse<T extends string> = Response<({
"endpoint_1": Data;
"endpoint_2": DataWidthLabel;
} & { [key: string]: never })[T]>;
Lastly, the component itself needs to be generic so we can pass down the generic parameter to Props
:
function DataComp<E extends Endpoint>({ endpoint, children }: Props<E>) {
or
// NO React.FC!
const DataComp = <E extends Endpoint>({ endpoint, children }: Props<E>) => {