2

Example Code:

type PropsType = {top: number} | {bottom: number}

// A funtion that make something run at one direction by distance.
function run(props: PropsType) {
...
}

Expected:

run({top: 100}) or run({bottom: 100})

not run({top: 100, bottom: 100}) (which is the current)

not trigger suggtion have both props: enter image description here

Question:

So, how to limit the type with different situation, I don't want the props accept top and bottom at same time.

Yokiijay
  • 711
  • 2
  • 7
  • 18
  • I've searched everywhere but no good solution, maybe I should compromise by redesign the props : {direction: 'top' | 'bottom', distance: number} – Yokiijay Mar 22 '21 at 08:22

3 Answers3

2

You can use "never" keyword like this:

type PropsType = {top: number, bottom?: never} | {top?: never, bottom: number}

// A funtion that make something run at one direction by distance.
function run(props: PropsType) {
...
}
Vo Quoc Thang
  • 1,338
  • 1
  • 4
  • 5
1

You can make your union more stricted:

type PropsType = { top: number } | { bottom: number }

// credits goes to Titian Cernicova-Dragomir
//https://stackoverflow.com/questions/65805600/struggling-with-building-a-type-in-ts#answer-65805753
type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> =
  T extends any
  ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;

type StrictUnion<T> = StrictUnionHelper<T, T>

// A funtion that make something run at one direction by distance.
function run(props: StrictUnion<PropsType>) {

}

run({ top: 100, bottom: 100 }) // error
run({ top: 100 }) // ok
run({ bottom: 100 }) // ok

If this line :

type UnionKeys<T> = T extends T ? keyof T : never;

Playground

is not clear for you, please refer to the docs

When conditional types act on a generic type, they become distributive when given a union type. If we plug a union type into ToArray, then the conditional type will be applied to each member of that union.

0

What about optional parameter?

type PropsType = {top?: number, bottom?: number}

Usage will be:

run({top: 100});
run({bottom: 100});
Ashish Yadav
  • 1,901
  • 2
  • 17
  • 23