I was trying to fix some types regarding DataTable on carbon-components-react, but got stuck at making one property optional. I got to the point where I created my own demo to show this problem:
import React from "react";
interface Human {
name: string;
age: number;
address?: string;
}
interface ButtonProps<R extends Human> {
name: R["name"];
age: R["age"];
address?: R["address"];
onClick?: Function;
}
interface RenderProps<R extends Human> {
human: R;
getButtonProps(data?: ButtonProps<R>): ButtonProps<R>;
}
export interface DataTableProps<R extends Human> {
rows: R[];
render(props: RenderProps<R>): React.ReactNode;
}
class DataTable<R extends Human> extends React.Component<DataTableProps<R>> {
render() {
return this.props.rows.map((h) => {
const buttonProps: () => Human = () => ({ ...h }); // This is only to be able to see the type of buttonProps in IDE
return this.props.render({ human: h, getButtonProps: buttonProps });
});
}
}
interface TableButtonProps {
name: string;
address?: string;
}
const TableButton = (props: TableButtonProps) => (
<button>Button for {props.name}</button>
);
export const Demo = () => {
// This works
const man1: Human = {
name: "Anna",
age: 30,
};
// This seems to be ok since "address" is optional
// but this isn't working!
const man2 = {
name: "Tom",
age: 32,
};
// This works
const man3 = {
name: "John",
age: 40,
address: "404 Street Unknown",
};
return (
<DataTable
rows={[man2]}
render={({ getButtonProps }) => {
return <TableButton {...getButtonProps()} />;
}}
></DataTable>
);
};
The error I am getting at TableButton:
Type '{ name: string; age: number; address?: unknown; onClick?: Function | undefined; }' is not assignable to type 'TableButtonProps'.
Types of property 'address' are incompatible.
Type 'unknown' is not assignable to type 'string | undefined'.
Type 'unknown' is not assignable to type 'string'. TS2322
The address property has unknown type for some reason. When I use syntax like man1 or man3 everything is working, you can replace it at rows=. Why is man2 not working even though the type is still set to extend Human? Is TypeScript getting lost?
You can test this by initializing project using npx create-react-app mydemo --template=typescript
// Edit:
interface ButtonProps<R extends Human> {
name: Human["name"];
age: Human["age"];
address?: Human["address"];
onClick?: Function;
}
Also seems to be fixing this issue and "protect" address type.
