skip to Main Content

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.

2

Answers


  1. According to what I see, you shouldn’t need to do anything to get this to work. types/index.d.ts does export * from './dropbox_types';, and WriteModeOverwrite is exported from types/dropbox_types.d.ts within the files namespace. I think you just need to add files to your list of imports (in import {...} from 'dropbox') and then use files.WriteModeOverwrite. Ex.

    import { type files } from "dropbox"
    let foo: files.WriteModeOverwrite;
    

    let foo is just an example of using the type in a type context ("foo" is a pretty standard example-variable name). You can use files.WriteModeOverwrite in whatever type context you want. The fact that you can’t use it where you want to use it is because you’re not supposed to use it like that– that’s not a type context. That’s a value context (the value part of an object’s key-value entry)… what are you even trying to do? You need to put a value there and then type-annotate it / type-assert it. Ex.

    Unfortunately, I don’t actually know what you’re supposed to use there. It’s either "overwrite", or {".tag": "overwrite"}. Searching public GitHub repos, I see both in usage. It doesn’t help that the official upload example doesn’t show usage of that argument (at the time of this writing). Try both and see which actually does what you expect.

    Login or Signup to reply.
  2. 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:

    TS Playground

    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
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search