I'm making a browser app in VS Code in Typescript that uses the Dropbox SDK.
This import works:
import { Dropbox, DropboxAuth, DropboxResponse, DropboxResponseError } from 'dropbox';
This upload code works too:
const uploadResult = await dropbox.filesUpload(
{path: constants.dropboxFilename, contents: journalString});
But when I write this, to allow overwriting in uploads and prevent 409 error:
const uploadResult = await dropbox.filesUpload(
{path: constants.dropboxFilename, contents: journalString, mode: WriteModeOverwrite});
I can't get access to the definition of WriteModeOverwrite
because it's in node_modules/dropbox/types/dropbox_types.d.ts
How do I add this definitions file to my project, so both VS Code and TSC see it?
My project seems to see only node_modules/dropbox/types/index.d.ts
automatically. Thanks.
More info:
I tried adding import * as dropboxTypes from 'dropbox/types/dropbox_types';
too, but dropboxTypes.
anything is empty and autocomplete doesn't find any filemodes.
The mode
property has hint: files.CommitInfo.mode?: files.WriteMode | undefined
but if I try setting it to files.WriteMode
or WriteModeOverwrite
or files.WriteModeOverwrite
it's a type error. VS Code can't autocomplete anything on files
.
If I set the property to 'overwrite'
the code doesn't compile without error, but runs and uploads perfectly.
I empathize with you as this is (understandably) an unclear type. It appears that the types for this library are generated and the publishers haven't thoroughly considered the ergonomics of usage.
From dropbox/dropbox-sdk-js#207 (comment):
WriteMode
is a union, not a string, so you'll need to specify it like this:this.dropbox.filesUpload({contents: fileContent, path: fileName, mode:{".tag": "overwrite"}})
Dropbox really should provide an exported enum for you to use here.
This answer has explained how you can import the files
namespace and find the needed type — that's great!
But what if you didn't have access to that type (or the name of the type changes in the future, etc.)?
You can use TypeScript to infer the needed type using a few utility types. Here's an example:
import type { Dropbox } from "dropbox";
// This is the type that represents the first parameter for the `filesUpload` method:
type UploadArg = Parameters<Dropbox["filesUpload"]>[0];
//^? type UploadArg = files.UploadArg
// This type represents the `mode` property of the type above:
type WriteMode = UploadArg["mode"];
//^? type WriteMode = files.WriteMode | undefined
// However, it's still not obvious what `files.WriteMode` means...
// Utility types can be used to determine that:
type WriteModeKey = keyof NonNullable<WriteMode>;
//^? type WriteModeKey = ".tag"
type WriteModeTagValue = NonNullable<WriteMode>[".tag"];
//^? type WriteModeTagValue = "overwrite" | "add" | "update"
// Bingo! We need a type like this:
type WriteModeOverwrite = Extract<WriteMode, { ".tag": "overwrite" }>;
//^? type WriteModeOverwrite = files.WriteModeOverwrite
// It can be used to annotate your `mode` value like this:
const mode: WriteModeOverwrite = { ".tag": "overwrite" };
declare const dropbox: Dropbox;
declare const otherProps: Pick<UploadArg, "path" | "contents">;
dropbox.filesUpload({
...otherProps,
mode,
}); // Ok