为什么它不起作用,当我检查 phone
是否存在时。 TypeScript 应该捕捉到并知道 phone
是否存在,那么它必须是 AddressWithPhone
接口。
这么久了,我可能没有正确定义类型,
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 游乐场:
答案 0 :(得分:0)
当您执行 <T = Address | AddressWithPhone>
时,您将 T
的默认值设置为联合 Address | AddressWithPhone
。您实际上并未限制 T
的可能值,因此 T
仍然可以是任何值。
您想使用 extends
来限制 T
的可能值。这仍然不能与联合完美配合,因为 phone
未在 Address
上定义,并且必须在联合的所有成员上定义属性才能访问它们。我们想要一个具有 Address
必需和 phone
可选的所有属性的基本类型。有很多方法可以定义它,但这里有一个:
type BaseAddress = Address & Partial<AddressWithPhone>
const something = <T extends BaseAddress>(props: EditAddressProps<T>): string => {
答案 1 :(得分:0)
这是另一种方法:
type AddressBase = {
street: string;
zip: string;
state: string;
city: string;
};
type Address =
| AddressBase
| AddressBase & {
phone: string;
}
type EditAddressProps<T> = {
address: T;
onChange: (address: T) => unknown;
}
const withPhone = (props: EditAddressProps<any>): props is EditAddressProps<AddressBase & {
phone: string;
}> => Object.prototype.hasOwnProperty.call(props.address, 'phone');
const withoutPhone = (props: EditAddressProps<any>): props is EditAddressProps<AddressBase> =>
!withPhone(props)
const something = < T extends Address>(props: EditAddressProps<T>) => {
if (withPhone(props)) {
const phone = props.address.phone; // string
props.onChange({
street: '123',
zip: 'AB12345',
state: 'TX',
city: 'Dallas',
phone: 'sdf', // phone is required here
})
return 'hello'
}
if (withoutPhone(props)) {
const x = props.address // no phone
props.onChange({
street: '123',
zip: 'AB12345',
state: 'TX',
city: 'Dallas',
phone: 'sdf' // expected error, phone property is redundant here
})
}
const defaultCase = props; // EditAddressProps<T>
return 'default'
}
如果您要处理带有泛型的联合类型,我建议您使用类型保护,因为 TS 无法像您期望的那样缩小范围