Given you have a specific set of allowed values, you may do it like https://tsplay.dev/NlXgrN
type ValidateUniqueArray<T, A extends T[]> = | A extends [infer F, ...infer L] ? (L extends Exclude<T, F>[] ? [F, ...ValidateUniqueArray<Exclude<T, F>, L>] : [F, Exclude<T, F>?] ) : [T?, ...unknown[]] ; type ValidateCompleteUniqueArray<T, A extends any[]> = | [T] extends [never] ? [] : A extends [infer F, ...infer L] ? (F extends T ? [F, ...ValidateCompleteUniqueArray<Exclude<T, F>, L>] : [T, ...ValidateCompleteUniqueArray<T, L>] ) : [T] ; type conforms<T, V> = T extends V ? T : V; function uniqueArray<T>() { return { partial<A extends T[]>(a: conforms<A, ValidateUniqueArray<T, A>>): A { return a as A; }, complete<A extends T[]>(a: conforms<A, ValidateCompleteUniqueArray<T, A>>): A { return a as A; }, } } let a1 = uniqueArray<1 | 2 | 3 | 4>().partial([ 1, 2, 3, 4 // ok ]) let a2 = uniqueArray<1 | 2 | 3 | 4>().partial([ 1, 1 // Type '1' is not assignable to type '2 | 3 | 4'.(2322) ]) let a3 = uniqueArray<1 | 2 | 3 | 4>().partial([ 1, 'foo' // Type 'string' is not assignable to type '2 | 1 | 3 | 4'.(2322) ]) let b1 = uniqueArray<1 | 2 | 3 | 4>().complete([ 1, 2, 3, 4 // ok ]) let b2 = uniqueArray<1 | 2 | 3 | 4>().complete([ 1, 2, 3, 1 // Type '1' is not assignable to type '4'.(2322) ]) let b3 = uniqueArray<1 | 2 | 3 | 4>().complete([ 1, 2, 3, 'foo' // error ]) let b4 = uniqueArray<1 | 2 | 3 | 4>().complete([ 1, 2, 3 // Argument of type '[1, 2, 3]' is not assignable to parameter of type '[1, 2, 3, 4]'. ])