Reputation: 1937
I have created a type by merging some interfaces. For some reason TypeScript assumes my type is going to be of type never
. Could you point out what I am doing wrong so that TypeScript does that?
type OrganizationAccount = Account & DetailedAccount & AccountSelection;
interface Account {
name: string;
created_on: string;
}
interface DetailedAccount {
account_type: string;
status: string;
}
interface AccountSelection {
isSelected?: boolean;
}
My first API request returns just the Account
properties (name
and created_on
).
The user may get the details by clicking a button which then makes another request and after it receives extra properties spreads the account object adding DetailedAccount
properties.
function getAccountDetails(account: OrganizationAccount) {
setOrganizationAccounts((prevState: OrganizationAccount[]) => {
return prevState.map(organizationAccount => {
return organizationAccount.name === account.name
? {
...organizationAccount,
...accountDetailsRes,
}
: organizationAccount;
});
});
});
}
Later I am checking whether account_type
is present and based on that I display different results however, this is where TypeScript thinks my account
variable is of type never
.
function accountType(account: OrganizationAccount) {
if (!('account_type' in account)) { // Here account === OrganizationAccount
console.log('account', account); // Here account === never
return 'Loading...';
}
return account.account_type;
}
Upvotes: 1
Views: 525
Reputation: 35
Try this:
type A = {
mayVar1: string;
mayVar2: boolean;
};
type B = {
mayVar3: string;
mayVar4: boolean;
};
type AandB = A & B;
Upvotes: 0
Reputation: 6745
if (!('account_type' in account)) {
is always false in the TypeScript world because the property account_type
is mandatory in OrganizationAccount
.
You probably want to set OrganizationAccount
to
type OrganizationAccount = (Account | Account & DetailedAccount) & AccountSelection;
I prefer
type OrganizationAccount = (Account | DetailedAccount) & AccountSelection;
interface Account {
name: string;
created_on: string;
}
interface DetailedAccount extends Account {
account_type: string;
status: string;
}
interface AccountSelection {
isSelected?: boolean;
}
A working example:
type OrganizationAccount = (Account | Account & DetailedAccount) & AccountSelection;
interface Account {
name: string;
created_on: string;
}
interface DetailedAccount {
account_type: string;
status: string;
}
interface AccountSelection {
isSelected?: boolean;
}
let a: OrganizationAccount = {
name: 'a',
created_on: 'string',
isSelected: false
};
a.name = 'a';
a.created_on = 'string';
a.isSelected = true;
let b: OrganizationAccount = {
name: 'b',
created_on: 'string',
isSelected: false,
account_type: 'type',
status: 'string'
};
b.name = 'b';
b.created_on = 'string';
b.isSelected = true;
b.account_type = 'type';
b.status = 'string';
function f(account: OrganizationAccount) {
console.log(account.name);
if ('account_type' in account) {
console.log(account.account_type);
}
}
f(a);
f(b);
Upvotes: 1