75101


コードはNext.jsのコードをTypeScriptに変換する章で登場したのですが、 `GetStaticPaths`
の先頭が大文字なのとVScodeだと下記の部分が赤波線でエラーに `can not find name
GetStaticPaths`と出ます。VScodeでは関数の先頭を大文字にする習慣等があるのでしょうか？

また赤波線を取り除くにはどうしたら良いのでしょうか。

よろしくお願いします。

[code]

    export const getStaticPaths: GetStaticPaths = async () => {
        const paths = getAllPostIds()
        return {
            paths,
            fallback: false
        }
    }
    
    //JS
    // export async function getStaticProps({ params }) {
    //     const postData = await getPostData(params.id)
    //     return {
    //         props: {
    //             postData
    //         }
    //     }
    // }
    
    export const getStaticProps: GetStaticProps = async ({ params }) => {
        const postData = await getPostData(params.id as string)
        return {
            props: {
                postData
            }
        }
    }
    
    //これがpathを返す。
    //JS
    // export async function getStaticPaths() {
    //     const paths = getAllPostIds()
    //     return {
    //         paths,
    //         fallback: false
    //     }
    // }
    
[/code]

### 参照

<https://nextjs.org/learn/excel/typescript/nextjs-types>


CC BY-SA 4.0
2021-04-05T01:05:39.527
75087
2021-04-05T17:03:27.150
2021-04-05T06:02:52.700
22565
22565
question
javascript typescript next.js
TypeScriptでexport const getStaticPaths: GetStaticPathsのGetStaticPathが何を意味するのか分からない。


エラーはimport文が不足していたことが原因だったという前提で回答させて頂きます。

更に回答前の前提として、TypeScript(TS)は以下のような特徴があります。

  1. TSは変数や関数などに型(型注釈)をつけることができる
  2. 型には別名(alias)を付けることができる
  3. 型Aliasは export できる 
    * 他のファイルでその型Aliasが利用できるようになります
  4. 型同士の構造に互換性があれば、代入などが可能
  5. 型が明示されていない場合、TypeScriptコンパイラにより型が推論される 
    * 特定の型に推論できなかった場合、`any`型になる

[code]

    // 1. 変数 value に number の型注釈をつけている
    //    (number型以外の値を代入しようとするとコンパイルエラーになります) 
    const value: number = 'any string'.length;
    
    // 2. 型には別名を付けることができる
    type EvenMonths            = 2 | 4 | 6 | 8 | 10 | 12
    type NumberArray           = Array<number>
    type ReturnBooleanFunction = () => boolean
    
    const evenMonth: EvenMonth = 2;
    
    // 4. 
    type HasOnlyA = { a: number }
    const hasAlsoB = { a: 10, b: 'b' };
    
    // HasOnlyA は `a: number` プロパティがある変数であれば代入可能
    const a: HasOnlyA = hasAlsoB;
    
    // 5. 型名が明示されていない場合は、型が推論される
    
    // number 型に推論される
    // (String.prototype.length がnumber型の為)
    const numberValue = 'any string'.length;
    
    // (any) => void 型に推論される
    // - 引数の value の型を推論するために使える情報が一切ないため
    // - `noImplicitAny` コンパイルオプションが指定されている場合はエラーになります
    const outputConsoleLog = (value) => { console.log(value); };
    
    
[/code]

* * *

> どうしてTypeScriptの場合 import { GetServerSideProps } from 'next'; が必要なのでしょうか？

next.jsが提供している `GetStaticPaths`型 や `GetServerSideProps`型
を参照しているからです。そのため定義元からimportする必要があります。

`Array<T>`や`Promise<T>`のような型は、通常`tsconfig.json`でTypeScriptが予め用意したものをグローバルで使用する設定になっているはずなので、これらの型を使用する際はimportする必要がありません。

<https://typescript-jp.gitbook.io/deep-dive/type-system/types>  
<https://typescript-jp.gitbook.io/deep-dive/type-system/lib.d.ts>

JSのコード上には型情報が一切存在しないため、TSではJSで書かれたライブラリが型安全に利用できるように、「型定義ファイル」というものがライブラリ側やDefinitelyTypedにより提供されています。

<https://github.com/DefinitelyTyped/DefinitelyTyped>

この型定義(型Aliasのようなもの)に沿ってコンパイルエラーが起きないようにコーディングしていれば、ライブラリを正しく使えるようになっています。

なのでこれらの型を利用せずに `: GetStaticPaths` などの型注釈自体を削除しても良いのですが、引数がany型になったり、IDE(VS
Code)でコード補完が効かなくなったりして不便ですし、ライブラリの使用方法を誤る可能性があります。  
(コードやコンパイラオプションによってはそもそもコンパイルが通りません)

特に `const getStaticProps: GetStaticProps`
の方は代入している関数の引数に型注釈が一切ありませんが、`GetStaticProps`のおかげで自動的に
`GetStaticPropsContext`に推論されます。  
(これに存在しないプロパティにはそもそもアクセスができない)

<https://github.com/vercel/next.js/blob/v10.1.3/packages/next/types/index.d.ts#L93-L110>

[code]

    export type GetStaticProps<
      P extends { [key: string]: any } = { [key: string]: any },
      Q extends ParsedUrlQuery = ParsedUrlQuery
    > = (context: GetStaticPropsContext<Q>) => Promise<GetStaticPropsResult<P>>
    
[/code]

* * *

**余談**

`GetStaticPaths`は簡単に言えば、`context:
GetStaticPathsContext`を引数に取り、`GetStaticPathsResult<P>`型の値が返るPromiseを返す型です。

<https://github.com/vercel/next.js/blob/v10.1.3/packages/next/types/index.d.ts#L125-L132>

[code]

    export type GetStaticPaths<P extends ParsedUrlQuery = ParsedUrlQuery> = (
      context: GetStaticPathsContext
    ) => Promise<GetStaticPathsResult<P>>
    
[/code]

質問文のコードでは引数無しのasync関数を代入してますが、エラーにはなりません。

TSはJSのスーパーセットとして開発されているため、JSとしてvalidなコードはTSでもvalidです。  
(ただし前述の通り、コンパイラオプション設定によってエラーになります)

JSでイベントハンドラなどの引数を使用しない場合に引数がない関数が渡せるように、TSでも同じことができるようになっています。

これを実現するためにTSでは型の構造に互換性があるかどうか、で判断しています。  
(詳細は「TypeScript 構造的部分型」でググってください)


CC BY-SA 4.0
2021-04-05T12:36:01.557
75101
2021-04-05T17:03:27.150
2021-04-05T17:03:27.150
3068
3068
75087
answer