-
Notifications
You must be signed in to change notification settings - Fork 118
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
refactor(ts): initial conversion to TypeScript #285
Conversation
@QmarkC it seems a little weird that we saw a drop in coverage due to conversion, I'd hope we'd still be exercising the same API surface. I'll take a closer look towards the end of my work day 👍 |
Most of the new uncovered branches are due to use of optional chaining. I forgot to run coverage before submitting the PR. I'm used to the coverage check being part of test with my other projects. I've already fixed some of them, either by removing unnecessary branches or adding tests. The original commit on this PR was I also noticed that I was seeing slightly different coverage percentages when running
|
@bcoe branch coverage is now 98.93%. The remaining uncovered branches were previously uncovered as well.
|
lib/yargs-parser-types.ts
Outdated
|
||
export interface Options { | ||
/** An object representing the set of aliases for a key: `{ alias: { foo: ['f']} }`. */ | ||
alias?: Dictionary<string | string[]>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Options properties should not be all optional, for a better reuse in yargs
.
You should use instead Partial<Options>
when you need to use all optional options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mleguen I'll go ahead and make this change but I'm not sure I agree with it. Perhaps you could expand on how this makes it better for reuse in yargs
?
While both methods are practically the same, in my option it is a better practice to explicitly set the properties as optional for this use case. None of the options are required and they all can indeed be undefined. I think using Partial is fine when reusing an existing type and/or there are clear default values, such as with Configuration, but Options doesn't really have clear defaults for all its properties. A quick test with using Partial on the options parse argument but not with the scoped opts variable (like configuration) and setting the option properties to their fallback values (empty objects/arrays/etc...) broke a lot of tests. So we would have to use partial again there or do quite a bit of refactoring in elsewhere. From the perspective of using yargs-parser
as a dependency I think the optional properties is clearer on how to interact with the module as well. Also if later an option is required, then all of the Partial<Options>
uses will have to be refactored to use explicit optional properties for Options, so the explicit optional properties provides better long term support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps you could expand on how this makes it better for reuse in yargs
I find it always easier to add undefined
to a type (using ?
or Partial
) than to remove it.
Yargs builds an internal options structure (including yargs-parser options, but not only), none of it being optional as it deals with defaults by itself. Reusing your Options
type would have helped not writing it twice.
But if it too much of a hassle to do so, no problem for me.
@QmarkC Sorry, I don't have a lot of bandwidth at the moment, but I will try to make a decent review of this ASAP. |
@QmarkC likewise, I have been low bandwidth this month (I'm hoping to do some coding on the long weekend that's coming up in the USA). This work is really exciting, I was looking at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@QmarkC this is looking like a great start, I've left a few initial notes. One thing that jumps out at me, is there any approach we could take using generics that would make the return value of the parser more clever. Here's my example code:
import yargsParser from './lib/index.ts'
const argv = yargsParser(Deno.args, {
string: ['foo']
})
function testStringType (input: string) {
console.info(typeof input, input)
}
testStringType(argv.foo)
argv.foo
ends up having an any
type, it would be cool if we were able to:
- give the appropriate
string
type hints, if we've set thestring
key for the parse. - identified that the key might be
undefined
, unlessdemand
, or adefault
value is set.
@mleguen any thoughts on this?
const path = require('path') | ||
const { tokenizeArgString } = require('./build/lib/tokenize-arg-string') | ||
const util = require('util') | ||
const { yargsParser } = require('./build/lib') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're converting all of index.js
to index.ts
, my preference would be that we just call this a breaking change and delete index.js
.
package.json
would then just be updated, such that its main entry point is ./build/index.js
.
import camelCase = require('camelcase') | ||
import decamelize = require('decamelize') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One fringe benefit we get for yargs-parser out of the conversion to TypeScript, is that we can publish a version for deno.land.
Not for this PR, but I think we should vendor camelCase
and decamelize
. They're both fairly small deps, with 0 dependencies.
export interface Configuration { | ||
/** Should variables prefixed with --no be treated as negations? Default is `true` */ | ||
'boolean-negation': boolean; | ||
/** Should hyphenated arguments be expanded into camel-case aliases? Default is `true` */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these configuration keys should all be optional I believe, when testing I got:
TS2580 [ERROR]: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i @types/node`.
process = process || {env: []}
Until I updated them to be optional.
return parse(args.slice(), opts) | ||
} | ||
|
||
export { yargsParser } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's make yargsParser
the default
export (this goes along with dropping the index.js
).
@QmarkC wanted to bump this up, would love to get us over the finish line on some of this TypeScript work 👏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to land this as a starting point, in an effort to keep the TypeScript work moving along.
Sorry for the delay. I had a death in the family. I'll catch up on the out standing items you tagged me in within the next few days. |
Second step for #265, "Switch to typescript".
This PR moves and converts most of the root
index.js
tolib/index.ts
.