kevinnguy
kevinnguy

Reputation: 454

Detect duplicate values from properties in TypeScript interface

Is there a way to detect duplicate values from properties in a TypeScript interface? ex:

interface Props {
   foo: string;
   bar: string;
}

let x : Props = {
   foo: 'hello world',
   bar: 'hello world'
} 

// show TypeScript warning for foo and bar having the same value

Upvotes: 0

Views: 259

Answers (1)

jcalz
jcalz

Reputation: 328453

There's no concrete type in TypeScript that represents such a constraint. Instead, you could use a generic type and a helper function to produce values of that type. Like, for example, this:

const asDistinctProps = <F extends string, B extends string>(
    props: { foo: F, bar: Exclude<B, F> }
) => props;

Here, asDistinctProps is a generic function that takes an object with string-valued foo and bar properties. But the type of bar is constrained so that it cannot be the same value as the foo type... as long as you're dealing with string literal types and not just string:

let x = asDistinctProps({
    foo: 'hello world',
    bar: 'hello world' // error!
});

let y = asDistinctProps({
    foo: 'hello world',
    bar: 'goodbye cruel world'
}); // okay

So that works the way you want.


Do remember though that the compiler will often widen a string from its literal value to string, and at that point it's not possible to properly apply the constraint. Here:

let z: string = "hello";
asDistinctProps({foo: z, bar: "goodbye"}); // error! 

you are prevented from using asDistinctProps at all because the foo property is just string. And here:

asDistinctProps({ foo: "hello", bar: z }); // no error!

you are not prevented from specifying the same value twice because the compiler does not see string as conflicting with "hello".


So with the above caveats, it's sort of possible. In practice I'd probably make the constraint enforced primarily at runtime and not worry about having the type system involved too much. Okay, hope that helps; good luck!

Playground link to code

Upvotes: 1

Related Questions