user1283776
user1283776

Reputation: 21764

Interface that extends either of two interfaces and adds some properties?

Action should have the properties children, size? and variant?.

Action should also implement either of Button or Link.

How can I achieve this?

Here is my best attempt

interface Button {
    action: () => void;
    href?: never;
}
interface Link {
    href: string;
    action?: never;
}

interface Action extends Button | Link {
    children: string;
    size?: 'large' | 'small';
    variant?: 'secondary';
}

Error:

[tslint] Forbidden bitwise operation

The functional requirement I really have is that I want to create a type or interface that has some props plus either action or href, but not both action and href.

Upvotes: 3

Views: 357

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249696

An interface can't extends a union type unfortunately. You could use an intersection type instead:

interface Button {
    action: () => void;
    href?: never;
}
interface Link {
    href: string;
    action?: never;
}

type Action =  (Button | Link) & {
    children: string;
    size?: 'large' | 'small';
    variant?: 'secondary';
}

let a: Action = {
    href: "",
    children: "",
    size: "large"
}


let a2: Action = {
    action: () => { },
    children: "",
    size: "large"
}


let a3: Action = { // error
    href: ""
    action: () => { },
    children: "",
    size: "large"
}

Upvotes: 3

Related Questions