sveltejs / sapper-template

Starter template for Sapper apps
703 stars 215 forks source link

"Cannot use namespace 'Preload' as a type" error when typing preload function #286

Closed saylerb closed 3 years ago

saylerb commented 3 years ago

Not sure if this a mistake in the Sapper documentation, or an issue with the template, or something with how TypeScript is configured. I'm new to TypeScript, so apologies if there's something super obvious that I'm missing here.

Using a fresh install of the sapper template on node 14.15.0 (fermium) and running the TypeScript conversion script, I wanted to test out using the new types for the preload function using the code example in the docs.

However, using the example from the docs verbatim to add types to the preload in blog/index.svelte like this:

<script context="module" lang="ts">
  import type { Preload } from "@sapper/common";

  export const preload: Preload = function (this) {
    return this.fetch(`blog.json`)
      .then((r: { json: () => any }) => r.json())
      .then((posts: { slug: string; title: string; html: any }[]) => {
        return { posts };
      });
  };
</script>

I get the TypeScript compilation error:

~/workspace/sapper-typescript/src/routes/blog/index.svelte:2:3
Hint: 'Preload' is declared but its value is never read. (ts)
<script context="module" lang="ts">
  import type { Preload } from "@sapper/common";

~/workspace/sapper-typescript/src/routes/blog/index.svelte:4:25
Error: Cannot use namespace 'Preload' as a type. (ts)

  export const preload: Preload = function () {
    return this.fetch(`blog.json`)

Changing the type import to import type Common from @sapper/common fixes the compilation error, and the type of this is correctly inferred to be Common.PreloadContext:

<script context="module" lang="ts">
  import type Common from "@sapper/common";

  export const preload: Common.Preload = function (this) {
    return this.fetch(`blog.json`)
      .then((r: { json: () => any }) => r.json())
      .then((posts: { slug: string; title: string; html: any }[]) => {
        return { posts };
      });
  };
</script>

Is the description in the docs wrong? Or am I missing something about TypeScript, where the template's configuration might be wrong? Here's a link to the test repo I made with both the broken and fixed version as two different commits.

PatrickG commented 3 years ago

Why does your function has a this argument?

saylerb commented 3 years ago

@PatrickG that is the convention for specifying the type of this in TypeScript, as described in the Sapper Docs. https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#specifying-the-type-of-this-for-functions

PatrickG commented 3 years ago

No, that would be

function (this: Type) {}

You did not specify any Type.

Edit: I see it is like this in the example. Looks strange.

saylerb commented 3 years ago

I believe since I’m providing the return type, TypeScript can infer the type. Are you saying these docs are wrong? https://sapper.svelte.dev/docs#Typing_the_function

PatrickG commented 3 years ago

The example should work, whether you specify this as an argument or not (although you do not need to specify it).

I just tested it with a fresh install. It works if you remove the empty declare module lines in src/node_modules/@sapper/index.d.ts. There is already a PR that does this (https://github.com/sveltejs/sapper/pull/1598), but it is not released yet.

benmccann commented 3 years ago

Closing this since the fix has already been checked in. Thanks @PatrickG for helping with this!

saylerb commented 3 years ago

The example should work, whether you specify this as an argument or not (although you do not need to specify it).

I just tested it with a fresh install. It works if you remove the empty declare module lines in src/node_modules/@sapper/index.d.ts. There is already a PR that does this (sveltejs/sapper#1598), but it is not released yet.

Ah okay. Thanks for the heads up. I'll be looking out for that next release, I guess.