Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Explicit error messages in declaration files #14977

Closed
danvk opened this issue Apr 2, 2017 · 4 comments
Closed

Suggestion: Explicit error messages in declaration files #14977

danvk opened this issue Apr 2, 2017 · 4 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@danvk
Copy link
Contributor

danvk commented Apr 2, 2017

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:

  1. Write a better error message for the mapValues case. Something like:
  mapValues<U, TResult>(
    this: WrappedValue<U[]>,
    fn: any,
  ): error('Cannot use mapValues with a list type');
  1. 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 becomes string rather than "a" | "b") or get mysterious inferred never types. (Broken inference between index typed object and Record #14930)

TypeScript Version: 2.2.2

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Apr 2, 2017

This feels a little bit like subtraction types but with nominal typing. The C++ analog might be

template<type typename U, typename TResult>
auto mapValues(
    const std::vector<U>& xs,
    std::function<TResult, (U)> fn
) = delete;

@RyanCavanaugh RyanCavanaugh added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Apr 3, 2017
@danvk
Copy link
Contributor Author

danvk commented Apr 3, 2017

@aluanhaddad That would work. And hey, delete is already a JS keyword :)

@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature and removed In Discussion Not yet reached consensus labels May 8, 2017
@RyanCavanaugh
Copy link
Member

Seems like the only people who want this are me and danvk, which is sad. Anyway @deprecated does nicely for this now without having really difficult type system implications.

@danvk
Copy link
Contributor Author

danvk commented Jul 23, 2020

As consolation, the lodash typings have improved spectacularly since this was filed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants