sindresorhus / ow

Function argument validation for humans
https://sindresorhus.com/ow/
MIT License
3.81k stars 108 forks source link

TypeScript optional function argument throws error TS2345 with `ow.optional.function` #147

Closed kaatt closed 4 years ago

kaatt commented 5 years ago

Issuehunt badges

interface Options {
  foo?: (baz: number) => string
  bar: (baz: number) => string
  baz?: number
}

function func1(options: Options): any {
  const { foo, bar, baz } = options
  ow(bar, ow.function)
  ow(foo, ow.optional.function) // throws TS2345
  ow(baz, ow.optional.number) // doesn't throw
}

The above code throws this error:

src/test.ts:11:11 - error TS2345: Argument of type 'Predicate<Function>' is not assignable to parameter of type 'BasePredicate<((baz: number) => string) | undefined>'.
  Types of property '[testSymbol]' are incompatible.
    Type '(value: Function, main: Main, label: TimerHandler) => void' is not assignable to type '(value: ((baz: number) => string) | undefined, main: Main, label: TimerHandler) => void'.
      Types of parameters 'value' and 'value' are incompatible.
        Type '((baz: number) => string) | undefined' is not assignable to type 'Function'.
          Type 'undefined' is not assignable to type 'Function'.

11   ow(foo, ow.optional.function)
             ~~~~~~~~~~~~~~~~~~~~

Not sure what's wrong here. Is it a bug with ow's typings?

This workaround works:

if (foo) ow(foo, ow.function)

IssueHunt Summary #### [theguardianwolf theguardianwolf](https://issuehunt.io/u/theguardianwolf) has been rewarded. ### Backers (Total: $40.00) - [issuehunt issuehunt](https://issuehunt.io/u/issuehunt) ($40.00) ### Submitted pull Requests - [#184 Allow potentially undefined functions to be checked](https://issuehunt.io/r/sindresorhus/ow/pull/184) --- ### Tips - Checkout the [Issuehunt explorer](https://issuehunt.io/r/sindresorhus/ow/) to discover more funded issues. - Need some help from other developers? [Add your repositories](https://issuehunt.io/r/new) on IssueHunt to raise funds.
IssueHuntBot commented 5 years ago

@issuehunt has funded $40.00 to this issue.


sbencoding commented 5 years ago

Hi!
I can't seem to re-create the error.

import ow from './dist/source'

interface Options {
    foo?: (baz: number) => string
    bar: (baz: number) => string
    baz?: number
}

function test(options: Options): any {
    const { foo, bar, baz } = options
    ow(bar, ow.function)
    ow(foo, ow.optional.function)
    ow(baz, ow.optional.number)
}

const o1 = {
    bar: (x) => 'asd',
    baz: 2,
};

test(o1);

The above code doesn't throw any errors for me.
Maybe your options object that you pass to test doesn't look like this, so that's maybe where I'm wrong

qti3e commented 5 years ago

@kaatt It happens because you're using strictNullChecks, I will open a PR with a possible fix.

qti3e commented 5 years ago

After some more digging, I realized it's somewhat the expected behaviour. But you can use the non-null assertion operator. (!)

- ow(foo, ow.optional.function) // throws TS2345
+ ow(foo!, ow.optional.function)
TheGuardianWolf commented 4 years ago

I've fixed the issue by approaching it in the other direction, which seems to work well - tests are all still passing.

issuehunt-oss[bot] commented 4 years ago

@sindresorhus has rewarded $36.00 to @theguardianwolf. See it on IssueHunt