Closed
Labels
Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScriptAn idea for TypeScript
Description
It would be nice if type declaration files had a way to declare that an overload should never match and, if it does, to provide a helpful error message.
Context: I've been playing around with trying to write precise type declarations for Lodash's chain method. _.chain(array).mapValues() should be an error, but _.chain(dict).mapValues() shouldn't.
Here's the code I'm working with:
type DictIterator<Dict, TResult> = (value: Dict[keyof Dict], key: keyof Dict, collection: Dict) => TResult;
class WrappedValue<T> {
value(): T;
mapValues<Dict extends object, TResult>(
this: WrappedValue<Dict>,
fn: DictIterator<Dict, TResult>
): WrappedValue<{[k in keyof Dict]: TResult}>;
}
export default function chain<V>(value: V): WrappedValue<V>;
}When this method is used correctly, it deduces the type perfectly. But when it's used incorrectly, e.g. on an array instead of a Record type, the error message is cryptic:
chain({a: 1, b: 2}).mapValues(v => 1 + v).value(); // {a: number, b: number} (perfect!)
chain([1, 2, 3]).mapValues(v => 1 + v).value();
~~~~~
// error TS2365: Operator '+' cannot be applied to types '1' and 'number | { <U>(this: [number, number, number, number, number], callbackfn: (value: number, index:...'
This feels vaguely like the morass of C++ template error messages! It would be nice if I could either:
- Write a better error message for the
mapValuescase. Something like:
mapValues<U, TResult>(
this: WrappedValue<U[]>,
fn: any,
): error('Cannot use mapValues with a list type');- Match record types but not arrays. I've tried adding
Dict extends Record<K, V>to the declaration but I always either lose the precise key information (it becomesstringrather than"a" | "b") or get mysterious inferrednevertypes. (Broken inference between index typed object and Record #14930)
TypeScript Version: 2.2.2
Metadata
Metadata
Assignees
Labels
Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScriptAn idea for TypeScript
Activity
aluanhaddad commentedon Apr 2, 2017
This feels a little bit like subtraction types but with nominal typing. The C++ analog might be
danvk commentedon Apr 3, 2017
Aluan Haddad (@aluanhaddad) That would work. And hey,
deleteis already a JS keyword :)RyanCavanaugh commentedon Jul 22, 2020
Seems like the only people who want this are me and danvk, which is sad. Anyway
@deprecateddoes nicely for this now without having really difficult type system implications.danvk commentedon Jul 23, 2020
As consolation, the lodash typings have improved spectacularly since this was filed!