Next.js应用转换为TypeScript方法demo
作者:Jovie 发布时间:2024-05-11 09:36:17
引言
如果你不确定TypeScript是什么,它基本上是一种建立在JavaScript之上的类型化语言。所有的JavaScript都是有效的TypeScript,但反之亦然。你可以在这里阅读更多关于它的信息,以及它如何与React/Next.js一起工作。你可以在你的项目中轻松地设置TypeScript,只需几个命令和一些小的重构,在这篇文章中,我将告诉你如何做!
添加TypeScript
最初添加TypeScript到你的Next.js项目很简单。只需通过运行以下命令来安装TypeScript。
npm install --save-dev typescript @types/react @types/node
然后,在你的项目根部创建一个空的 tsconfig.json文件,然后在你的项目的根部创建一个空的你可以手动完成,或者在你的项目根部运行以下命令。
touch tsconfig.json
然后使用 "npm run dev "启动你的项目,你应该在控制台中看到以下一行。
Next.js会在你的 tsconfig.json文件中加入一些预选的选项。我推荐的一个选项是在第11行将strict设置为true,以启用TypeScript的一些更严格的打字选项,但并不是必须的。
重构
你会发现你的项目仍然运行良好,这是因为你所有的.js或.jsx文件仍然是JavaScript。要将它们切换到TypeScript,只需将文件扩展名改为.ts或.tsx。
你现在可能又会遇到一些错误,所以我将讨论一些常见的错误。这里有一个JavaScript组件的例子,它使用API调用检索一些有趣的事实,并使用SSR渲染它们。这个组件使用的是TailwindCSS的样式,我强烈建议你看一下它。
import React, { useState } from 'react';
import axios from 'axios';
function fetchFact() {
//Just a simple get request which gets back a fact in a JSON object
return axios
.get('https://uselessfacts.jsph.pl//random.json?language=en')
.then((res) => {
return res.data;
});
}
//TS7031: Binding element 'facts' implicitly has an 'any' type.
export default function SSRExample({ facts }) {
return (
<div className="flex h-screen w-screen flex-col items-center justify-center bg-white text-3xl text-white">
<p className="mb-10 rounded bg-neutral-800 p-10">
Heres some fun facts!
</p>
<ul className="flex max-w-2xl flex-col gap-5 rounded bg-neutral-800 p-10 shadow">
{
//TS7031: Binding element 'id' implicitly has an 'any' type.
//TS7031: Binding element 'text' implicitly has an 'any' type.
facts.map(({ id, text }) => (
<li key={id}>{text}</li>
))
}
</ul>
</div>
);
}
//TS7031: Binding element 'query' implicitly has an 'any' type.
export async function getServerSideProps({ query }) {
const { count } = query;
const promises = [...new Array(Number(count))].map(() => fetchFact());
const facts = await Promise.all(promises);
return {
props: {
facts,
},
};
}
输入道具
我在这个组件中得到的第一个错误是,TypeScript不知道我的道具是什么类型。这在严格模式下会导致一个错误,因为我们不允许使用任何道具。为了解决这个问题,我只需要为我的道具添加一个类型。
type Fact = {
id: string;
text: string;
};
type SSRExampleProps = {
facts: Fact[];
};
//TS7031: Binding element 'facts' implicitly has an 'any' type.
export default function SSRExample({ facts }: SSRExampleProps) { ... }
现在,来自初始道具的错误,以及试图映射事实数组的错误都消失了。
需要注意的一件事是,我们在这里使用了对象重构,这可能会掩盖props是一个函数参数的事实。你的props将永远是一个包含你提供的任何props的对象,而不是直接参数。
export default function SSRExample({ facts }: { facts: { id: string; text: string }[]})
export default function SSRExample(facts: { id: string; text: string }[])
GetXProps
这段代码中的另一个问题是,我们的"getServerSideProps()"函数不知道它的参数是什么。如果你对这个函数不熟悉,请查看我们这里的文章,了解服务器端渲染的介绍。如果你使用getStaticProps或getStaticPaths,情况也会一样。
为了解决这个问题,Next.js为每一种和它们的参数提供了类型。需要注意的一点是,这些类型是针对箭头函数的,所以如果你使用的是正常的函数体,你就必须重构你的函数。
下面是我们更新的 getServerSideProps():
export const getServerSideProps: GetServerSideProps = async ({ query }) => {
const { count } = query;
const promises = [...new Array(Number(count))].map(() => fetchFact());
const facts = await Promise.all(promises);
return {
props: {
facts,
},
};
};
还有一个小细节是,我们的 ***fetchFact()***函数没有一个类型。在Next.js函数的交互方式下,这并没有造成任何问题,但如果我希望在其他地方使用该函数,就会遇到问题。由于我们已经为这个事实做了类型,重构这个事实很简单。
function fetchFact(): Promise<Fact> {
//Just a simple get request which gets back a fact in a JSON object
return axios
.get('https://uselessfacts.jsph.pl//random.json?language=en')
.then((res) => {
return res.data;
});
}
状态
将类型添加到一个 ***useState()***钩子添加类型可以通过向函数提供一个类型参数来完成。我对前面的例子进行了重构,只允许点击一个按钮来获取一个额外的事实,并将这些额外的事实存储在状态中。
export default function SSRExample({ facts }: SSRExampleProps) {
const [extraFacts, setExtraFacts] = useState<Fact[]>([]);
const getAnotherFact = () => {
fetchFact().then((fact) => {
setExtraFacts((oldValue) => [...oldValue, fact]);
});
};
return (
<div className="flex h-screen w-screen flex-col items-center justify-center bg-white text-3xl text-white">
<p className="mb-10 rounded bg-neutral-800 p-10">
Heres some fun facts!
</p>
<ul className="flex max-w-2xl flex-col gap-5 rounded bg-neutral-800 p-10 shadow">
{
//TS7031: Binding element 'id' implicitly has an 'any' type.
//TS7031: Binding element 'text' implicitly has an 'any' type.
[...facts, ...extraFacts].map(({ id, text }) => (
<li key={id}>{text}</li>
))
}
<li>
<button
className="rounded bg-neutral-900 p-5 shadow"
onClick={() => getAnotherFact()}>
More
</button>
</li>
</ul>
</div>
);
}
TypeScript会尽力从你的状态初始值中推断出类型,但对于像这个事实数组这样更复杂的例子,我们必须包括类型参数。
希望这些例子足以帮助你在Next.js项目中开始使用TypeScript。TypeScript是一种非常有用的语言,可以帮助你写出更干净、更正确的代码,更多关于Next.js转换为TypeScript的资料请关注脚本之家其它相关文章!
来源:https://juejin.cn/post/7176279211399708732
猜你喜欢
- 一、什么是上下文管理器我们在处理文件的时候经常看到下面这样的代码,它即是上下文管理器:with open('test.txt'
- 前言今天我要教大家的是 如何实现nonebot插件之ChatGpt注意,本文涉及异步爬虫,json文件读写等知识点准备1.获取开发者key获
- 本文以YOLOv5-6.1版本为例一、Add1.在common.py后加入如下代码# 结合BiFPN 设置可学习参数 学习不同分支的权重#
- 本文实例讲述了Laravel框架执行原生SQL语句及使用paginate分页的方法。分享给大家供大家参考,具体如下:1、运行原生sqlpub
- 查看逻辑读前10的SQL:set linesize 300;set pagesize 300;set long 50000;SELECT *
- 本文实例讲述了Python批量重命名同一文件夹下文件的方法。分享给大家供大家参考。具体分析如下:朋友发了一个文件夹过来,里面的图片都以 .t
- 前言Python本身已有顺序表(List、Tupple)的实现,所以这里从栈开始。什么是栈想象一摞被堆起来的书,这就是栈。这堆书的特点是,最
- 下面一段代码给大家介绍python 处理微信对账单数据,具体代码如下所示:#下载对账单并存储到数据库@app.route("/bi
- <body> <script> //关闭DIV MENU function MenuClose() { var Me
- 在使用一些 Javascript 框架时,或许会看到类似的代码var MyClass = new Class({initialize: fu
- 拼接table请将以下代码直接运行:换下bootstrap.css jquery-1.12.3.min.js bootstrap-pagin
- 功能:为连连看游戏提供连接算法 说明:模块中包含一个Point类,该类是游戏的基本单元“点”,该类包含属性:x,y,value。 其中x,y
- 栈(Stack)在计算机领域是一个被广泛应用的集合,栈是线性集合,访问都严格地限制在一段,叫做顶(top)。 举个例子,栈就想一摞洗干净的盘
- 利用Python正则表达式匹配字符串中的http链接。主要难点是用正则表示出http 链接的模式。import repattern = re
- Vue3 ref获取DOM元素<div ref="divBox">Hello</div>impo
- 索引的概念MySQL索引是一种用于加速数据库查询的数据结构,它类似于书籍的目录,能够快速指导我们找到需要的信息。MySQL索引可以根据一定的
- 如下所示:daffodil = int(input('请输入一个三位数:'))if daffodil == pow(daff
- 网上存在这么一个例子 obj = pd.Series([7,-5,7,4,2,0,4])obj.rank()输出为:0 6.51
- 修改镜像源的原因是pip和conda默认国外镜像源,所以每次安装模块pip install ×××或者 conda install ×××的
- 问题:使用PyQt5开发桌面程序,实现功能为:按下按键,打开文件夹,选择文件夹,并将路径显示出来。解决方法:一、主要函数(直接能运行的代码见