Why it does not work, when I am checking if the phone
exists or not. The TypeScript should catch that and know if phone
exists, then it must be AddressWithPhone
interface.
Its been so long, I probably did not define the types correctly,
interface Address {
street: string;
zip: string;
state: string;
city: string;
}
interface AddressWithPhone extends Address {
phone: string;
}
interface EditAddressProps<T = Address | AddressWithPhone> {
address: T;
onChange: (address: T) => unknown;
}
const something = <T,>(props: EditAddressProps<T>): string => {
// Error: Property 'phone' does not exist on type 'T'
if (props.address.phone) {
return 'Its AddressWithPhone';
}
return 'Its Address without phone';
}
TS Playground:
When you do <T = Address | AddressWithPhone>
you are setting the default value of T
to the union Address | AddressWithPhone
. You haven't actually constrained the possible values of T
so T
still could be anything.
You want to use extends
to limit the possible values of T
. This still doesn't work perfectly with a union because phone
is not defined on Address
, and properties must be defined on all members of a union in order to access them. We want a base type with all properties of Address
required and phone
optional. There's a lot of ways to define that, but here's one:
type BaseAddress = Address & Partial<AddressWithPhone>
const something = <T extends BaseAddress>(props: EditAddressProps<T>): string => {