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
Add TypeScript definition and require Node.js 6 #17
Conversation
Thanks for creating a type definition 🙌 |
@sindresorhus You're welcome 😄 I've been looking forward to add Typescript definitions to your repos for a while. Glad you've started accepting them 👍 |
Still getting a few errors when running tests, not too sure if these are valid errors. 🤔
CC: @sindresorhus $ npm t
> write-json-file@2.3.0 test /Users/denis/Github/write-json-file
> xo && ava
index.d.ts:1:6
✖ 1:6 Parsing error: Unexpected token Replacer
index.js:52:4
✖ 52:4 Use object destructuring. prefer-destructuring
2 errors
npm ERR! Test failed. See above for more details. |
index.d.ts
Outdated
indent?: string | number | null; | ||
detectIndent?: boolean; | ||
sortKeys?: boolean | ((a: string, b: string) => number); | ||
replacer?: Replacer | Array<number | string> | null; |
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.
This should not be null
.
index.js
Outdated
module.exports.default = (fp, data, opts) => { | ||
return makeDir(path.dirname(fp), {fs}) | ||
.then(() => init(main, fp, data, opts)); | ||
}; |
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.
Instead of duplicating the code here, assign the method to a variable and then assign that variable to both module.exports
and module.exports.default
.
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.
👍 makes sense
package.json
Outdated
], | ||
"types": "index.d.ts", |
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.
This is not needed. From the style guide:
You don't need to add a typings field to package.json as TypeScript will infer it from the name.
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.
Sounds good, didn't know this wasn't required, good to know.
index.d.ts
Outdated
} | ||
|
||
/** | ||
* Stringify and write JSON to a file atomically |
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.
Should end in a dot.
index.d.ts
Outdated
|
||
interface Options { | ||
indent?: string | number | null; | ||
detectIndent?: boolean; |
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.
Is there any way to define default arguments in the types themselves instead of in the docs?
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.
Good question, I don't think it's possible as an interface.
[ts] A parameter initializer is only allowed in a function or constructor implementation.
You can do it if the types are created from a .ts
file
index.d.ts
Outdated
* @param {boolean} [options.detectIndent=false] Detect indentation automatically if the file exists. | ||
* @param {boolean|function} [options.sortKeys=false] Sort the keys recursively. Optionally pass in a compare function. | ||
* @param {function|Array<number|string>|null} [options.replacer] Passed into JSON.stringify. | ||
* @param {number} [options.mode=0o666] Mode used when writing the file. |
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.
From the style guide:
@param should not include the parameter type.
Since it's inferred from the type definition already and just results in duplication.
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.
👍
index.d.ts
Outdated
* @param {number} [options.mode=0o666] Mode used when writing the file. | ||
* @returns {void} | ||
* @example | ||
* const writeJsonFile = require('write-json-file'); |
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.
Use import
index.d.ts
Outdated
* | ||
* writeJsonFile('foo.json', {foo: true}).then(() => { | ||
* console.log('done'); | ||
* }); |
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.
Use this instead:
(async () => {
await writeJsonFile('foo.json', {foo: true});
console.log('done');
})();
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 like this example as well
index.d.ts
Outdated
* | ||
* @param {string} filepath Filepath | ||
* @param {any} data Data | ||
* @param {object} [options] Optional parameters |
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.
No need to have a description for these 3 parameters as the name is clear enough.
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.
Fair enough, dropping those params can be extracted from the Types
Yeah... You have to exclude the type definition file from being linted because of |
I'm also looking for feedback on the style guide. Anything that could be clearer/improved? Anything you strongly disagree with? You should probably read it again as I have updated it after reviewing this PR. |
package.json
Outdated
}, | ||
"scripts": { | ||
"test": "xo && ava" | ||
"test": "xo --ignore index.d.ts && ava" |
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.
Do it like the example is shared: https://github.com/sindresorhus/delay/blob/c17e29b13c20e6be35d64d75f45ce174bb793158/package.json#L48-L52
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.
👍 Sounds good!
index.d.ts
Outdated
export function sync(filepath: string, data: any, options?: Options): void; | ||
|
||
/** | ||
* Stringify and write JSON to a file atomically |
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.
Should end in a dot.
index.d.ts
Outdated
* | ||
* Creates directories for you as needed. | ||
* | ||
* @returns {Promise<void>} |
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.
This is moot as it has no description and therefore is better documented by the type definition itself.
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.
👍 yea it's pretty pointless, it is defined by the Types
index.d.ts
Outdated
* | ||
* Creates directories for you as needed. | ||
* | ||
* @returns {void} |
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.
index.d.ts
Outdated
* | ||
* @returns {void} | ||
* @example | ||
* import * as writeJsonFile from 'write-json-file'; |
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.
Should be import writeJsonFile from 'write-json-file';
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.
🤔 ... to access .sync()
you need to add import * as
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.
Ah, good point 👍
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 guess if you use Babel this example is correct, I'll change it to:
import writeJsonFile from 'write-json-file';
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.
Most Typescript users kinda got used to adding import * as
, no need to include it.
Most docs are mixed between Babel & Typescript, we can keep as the Babel way
index.d.ts
Outdated
* import writeJsonFile from 'write-json-file'; | ||
* | ||
* (async () => { | ||
* await writeJsonFile('foo.json', {foo: 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.
Incorrect indent
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.
🤦♂️
Need feedback on: #17 (comment)
We need to define default values somewhere for improved auto-completion experience. |
// @brandon93s @NeekSandhu Would you be able to help review this? |
@sindresorhus I've looked over all your comments and I hope we've covered everything 😄 Got another PR sindresorhus/load-json-file#15 with the same changes. I'm done for commits, unless you have more comments and reviews. Let me know if you come up with a solution for #17 (comment) |
Looks good to me. For #17 (comment), unfortunately I don't think there is a good way for defaults to be defined on an interface. Adding the default to the interface documentation would at least make it visible in the intellisense: /**
* Detect indentation automatically if the file exists.
*
* Default: false
*/
detectIndent?: boolean; |
index.d.ts
Outdated
* writeJsonFile.sync('foo.json', {foo: true}); | ||
* console.log('done'); | ||
*/ | ||
export function sync(filepath: string, data: any, options?: Options): void; |
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.
data
can't really be any
. For example, passing in undefined
will throw a TypeError
. We could attempt to express valid JSON values to be more specific here.
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.
Consider the fact that even in TypeScripts "official" lib.d.ts
file, the signature for JSON.stringify( ... )
is
JSON.stringify(value: any, replacer?: (key: string, value: any) => any, ...): string;
That means even the TypeScript team couldn't come with a reliable, sound way to describe JSON.
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.
There's always the object
type, however I kinda like using any
for this param.
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.
@brandon93s was hoping to prevent passing undefined
(which causes TypeError
), the problem is that no signature of any kind (as of ts@3.0.1
) can prevent that from happening.
function foo(a: object | number | string): void { }
// ts won't complain i.e no red squiggly lines
foo(undefined)
// no complains here either
foo(null)
EDIT
I was wrong, I forgot about strictNullChecks
option that TypeScript has for enforcing this. So in theory data: object | string | number
is better than data: any
. It'll remind the user of bad input as long as they have strictNullChecks
options engaged.
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.
Yeah, let's make it strict. Can be a type called JSONStringifyable
maybe.
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.
package.json
Outdated
} | ||
}, | ||
"xo": { | ||
"ignores": [ |
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.
The indentation is off. These lines are using tabs and the others are using spaces.
I know @sindresorhus switched to tabs for package.json because npm preserves them nowadays. But think it should be done in a separate commit.
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.
👍 fixed
As far as #17 (comment) goes, like @brandon93s said, unfortunately not possible yet. I've been using the method he advised, i.e to describe the default value in comment(s), works really well IMO. |
Future commit will convert package.json to tabs
Added defaults using the |
According to https://twitter.com/felixfbecker/status/1031660800413454337, we can use the |
wow...totally TIL thing. It's even worth mentioning in your style guide. |
@@ -1 +1,2 @@ | |||
node_modules | |||
yarn.lock |
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.
Add newline at the end of the file.
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.
Thanks for catching this 👍
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.
Added newline
While the context is heated up, have you considered sindresorhus/ama#554 |
|
* Creates directories for you as needed. | ||
* | ||
* @example | ||
* import * as writeJsonFile from 'write-json-file'; |
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.
@sindresorhus FYI: I've changed it back to import * as
syntax for the .sync()
example.
Reason: Since this is a Typescript definition, it makes more sense to reference the example in the "Typescript" way.
index.d.ts
Outdated
* writeJsonFile.sync('foo.json', {foo: true}); | ||
* console.log('done'); | ||
*/ | ||
export function sync(filepath: string, data: object | number | string, options?: Options): void; |
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 think we should make object | number | string
a named type called JSONStringifyable
? It would more clearly explain why it randomly only accepts object/number/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.
Ok! I'll add it
index.d.ts
Outdated
* | ||
* @default false | ||
*/ | ||
sortKeys?: SortKeys | boolean; |
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 think boolean
should be first as it should be sorted by most common usage, and most users will only ever need to set {sortKeys: 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.
👍 sounds good to me
This is perfect now. Thanks for your great work and patience, @DenisCarriere 🙌 |
@sindresorhus You're welcome! Thanks for building awesome open source tools! 🙌 |
Add TypeScript definition to
write-json-file
Ref: https://github.com/sindresorhus/typescript-definition-style-guide
sindresorhus/ama#439 (comment)