Skip to content

Commit 0fcde9b

Browse files
committed
Fix issue with generic and dynamic props
1 parent d4acc79 commit 0fcde9b

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

packages/connect-react/src/hooks/form-context.tsx

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,9 @@ import isEqual from "lodash.isequal";
1111
import { useQuery } from "@tanstack/react-query";
1212
import type {
1313
ConfigurableProp,
14-
ConfigurablePropApp,
15-
ConfigurablePropBoolean,
16-
ConfigurablePropInteger,
17-
ConfigurablePropString,
18-
ConfigurablePropStringArray,
1914
ConfigurableProps,
2015
ConfiguredProps,
21-
DynamicProps,
16+
DynamicProps as SdkDynamicProps,
2217
Observation,
2318
ReloadPropsOpts,
2419
ReloadPropsResponse,
@@ -46,11 +41,21 @@ export type AnyFormFieldContext = Omit<FormFieldContext<ConfigurableProp>, "onCh
4641
onChange: (value: unknown) => void;
4742
};
4843

44+
/**
45+
* Auxiliary type to avoid breaking the generic chain given that `DynamicProps`
46+
* in the SDK is not generic. This prevents us from doing double casting and
47+
* destroying type information (i.e. `as unknown as T`).
48+
*/
49+
interface DynamicProps<T extends ConfigurableProps = ConfigurableProps>
50+
extends Omit<SdkDynamicProps, "configurableProps"> {
51+
configurableProps?: T;
52+
}
53+
4954
export type FormContext<T extends ConfigurableProps> = {
5055
component: Component;
5156
configurableProps: T; // dynamicProps.configurableProps || props.component.configurable_props
5257
configuredProps: ConfiguredProps<T>;
53-
dynamicProps?: DynamicProps; // lots of calls require dynamicProps?.id, so need to expose
58+
dynamicProps?: DynamicProps<T>; // lots of calls require dynamicProps?.id, so need to expose
5459
dynamicPropsQueryIsFetching?: boolean;
5560
errors: Record<string, string[]>;
5661
sdkErrors: SdkError[];
@@ -180,7 +185,7 @@ export const FormContextProvider = <T extends ConfigurableProps>({
180185
const [
181186
dynamicProps,
182187
setDynamicProps,
183-
] = useState<DynamicProps>();
188+
] = useState<DynamicProps<T>>();
184189
const [
185190
reloadPropIdx,
186191
setReloadPropIdx,
@@ -206,9 +211,14 @@ export const FormContextProvider = <T extends ConfigurableProps>({
206211
queryFn: async () => {
207212
const result = await client.components.reloadProps(componentReloadPropsInput);
208213
const {
209-
dynamicProps, observations, errors: __errors,
214+
dynamicProps: sdkDynamicProps,
215+
observations,
216+
errors: __errors,
210217
} = result as ReloadPropsResponse;
211218

219+
// Narrowing to generic T (ConfigurableProps) for downstream typing
220+
const dynamicProps = sdkDynamicProps as DynamicProps<T>;
221+
212222
// Prioritize errors from observations over the errors array
213223
if (observations && observations.filter((o) => o.k === "error").length > 0) {
214224
handleSdkErrors(observations)
@@ -218,8 +228,8 @@ export const FormContextProvider = <T extends ConfigurableProps>({
218228

219229
// XXX what about if null?
220230
// TODO observation errors, etc.
221-
if (dynamicProps) {
222-
formProps.onUpdateDynamicProps?.(dynamicProps);
231+
if (sdkDynamicProps && dynamicProps) {
232+
formProps.onUpdateDynamicProps?.(sdkDynamicProps);
223233
setDynamicProps(dynamicProps);
224234
}
225235
setReloadPropIdx(undefined);
@@ -240,7 +250,7 @@ export const FormContextProvider = <T extends ConfigurableProps>({
240250

241251
// XXX fix types of dynamicProps, props.component so this type decl not needed
242252
const configurableProps = useMemo(() => {
243-
let props: unknown = dynamicProps?.configurableProps || formProps.component.configurableProps || [];
253+
let props = dynamicProps?.configurableProps || formProps.component.configurableProps || [];
244254
if (propNames?.length) {
245255
const _configurableProps = [];
246256
for (const prop of (props as ConfigurableProp[])) {

0 commit comments

Comments
 (0)