質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

2回答

547閲覧

jsonファイルを書き出す際に文字列置換をしようとするとタイプエラーになるのはなぜ??

snafkin999

総合スコア27

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2022/10/29 15:58

前提

TypeScriptでRSS記事を集めJSONファイルを書き出すプログラムを書いています。
プログラム内でJSONデータ内にある余計な文字を削除しようと思い、replaceで置換しようと考えましたが
なぜか”型がない”とlintエラーが発生してしまい、動作しません。命令文に型って必要なんですか?

型の理解が浅く、TypeScriptはエラーだらけで苦手です。

実現したいこと

JSONデータ内の余分な文字を削除したい

発生している問題・エラーメッセージ

イメージ説明

該当のソースコード

TypeScript

1import fs from "fs-extra"; 2import Parser from "rss-parser"; 3import { blogUrl } from "../blogUrl"; 4import { PostItem, Member } from "../types"; 5 6type FeedItem = { 7 title: string; 8 link: string; 9 contentSnippet?: string; 10 isoDate?: string; 11 dateMiliSeconds: number; 12}; 13 14function isValidUrl(str: string): boolean { 15 try { 16 const { protocol } = new URL(str); 17 return protocol === "http:" || protocol === "https:"; 18 } catch { 19 return false; 20 } 21} 22 23const parser = new Parser(); 24let allPostItems: PostItem[] = []; 25 26async function fetchFeedItems(url: string) { 27 const feed = await parser.parseURL(url); 28 29 if (!feed?.items?.length) return []; 30 31 // return item which has title and link 32 return feed.items 33 .map(({ title, contentSnippet, link, isoDate, content }) => { 34 return { 35 title, 36 contentSnippet: contentSnippet?.replace(/\n/g, ""), 37 link, 38 isoDate, 39 content: content?.match(/<img[^>]+>/i), 40 dateMiliSeconds: isoDate ? new Date(isoDate).getTime() : 0, 41 }; 42 }) 43 .filter(({ title, link }) => title && link) as FeedItem[]; 44} 45 46async function getFeedItemsFromSources(sources: undefined | string[]) { 47 if (!sources?.length) return []; 48 let feedItems: FeedItem[] = []; 49 for (const url of sources) { 50 const items = await fetchFeedItems(url); 51 if (items) feedItems = [...feedItems, ...items]; 52 } 53 return feedItems; 54} 55 56async function getMemberFeedItems(member: Member): Promise<PostItem[]> { 57 const { sources } = member; 58 const feedItems = await getFeedItemsFromSources(sources); 59 if (!feedItems) return []; 60 61 let postItems = feedItems.map((item) => { 62 return { 63 ...item, 64 }; 65 }); 66 67 return postItems; 68} 69 70(async function () { 71 for (const member of blogUrl) { 72 const items = await getMemberFeedItems(member); 73 if (items) allPostItems = [...allPostItems, ...items]; 74 } 75 allPostItems.sort((a, b) => b.dateMiliSeconds - a.dateMiliSeconds); 76 // 該当の箇所 77 allPostItems.replace(/\s+/g, ""); 78 fs.ensureDirSync(".contents"); 79 fs.writeJsonSync(".contents/posts.json", allPostItems); 80})(); 81

念のため型ファイルも載せます

Types.ts

1export type Member = { 2 role?: string; 3 bio?: string; 4 sources?: string[]; 5 websiteUrl?: string; 6}; 7 8export type PostItem = { 9 title: string; 10 link: string; 11 contentSnippet?: string; 12 isoDate?: string; 13 dateMiliSeconds: number; 14 content?: string; 15 itemData?: string; 16 item?: string; 17 replace?: string; 18}; 19

試したこと

types.tsに型を記載してみた。(ダメでした)

補足情報(FW/ツールのバージョンなど)

packege.json

1{ 2 "name": "verceltest", 3 "version": "0.1.0", 4 "private": true, 5 "scripts": { 6 "dev": "next dev", 7 "build": "next build", 8 "build:posts": "ts-node --project tsconfig.builder.json ./builder/posts.ts", 9 "start": "next start", 10 "lint": "next lint" 11 }, 12 "dependencies": { 13 "fs-extra": "^10.1.0", 14 "next": "13.0.0", 15 "react": "18.2.0", 16 "react-dom": "18.2.0", 17 "rss-parser": "^3.12.0", 18 "ts-node": "^10.9.1" 19 }, 20 "devDependencies": { 21 "@types/fs-extra": "^9.0.13", 22 "@types/node": "18.11.7", 23 "@types/react": "18.0.24", 24 "@types/react-dom": "18.0.8", 25 "eslint": "8.26.0", 26 "eslint-config-next": "13.0.0", 27 "typescript": "4.8.4" 28 } 29} 30

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2022/10/29 16:19

allPostItems は PostItem の配列なので、単純な文字列置換はできず、例えば各要素の title や content などを置換する必要があるのでは…。
snafkin999

2022/10/29 16:32

確かにtitleのところでreplace使ってました。 ありがとうございます!
guest

回答2

0

自己解決されたようですので、以下、余談として回答します。

質問に

なぜか”型がない”とlintエラーが発生してしまい、動作しません。

とありますが、発生しているエラーは lintエラーではなく typescriptの型チェックによるエラーです。エラーメッセージの後に ts(2339) とありますが、これの ts の部分で typescriptのエラーであることが分かります。2339 はエラー番号で、ある型にないプロパティを指定した場合にこの番号のエラーが発生します。今回の場合、allPostItems は配列ですが、配列にない replace プロパティをメソッドとして使おうとしてこの 2339番エラーが発生しています。

型の理解が浅く、TypeScriptはエラーだらけで苦手です。

分かります。理解が浅いうちは Javascript の自由度が失われている気さえするかもしれませんね。しかし今回のコードの問題箇所はTypescriptではなくJavascriptだと動かして始めてエラーになって気がつくものです。それを動かす前に知ることができるのは、特にチーム開発で、自分の書いたコードで他のメンバーが動かしてみたら(typescriptなら型エラーになっていたであろう部分で)実行時にエラーになって迷惑がかかる可能性が少なくなるという点でだいぶ気が楽です。

Javascript は自由に書けて良かったけど

TypeScriptはエラーだらけで苦手

という場合は、一度は「 プログラミングTypeScript ―スケールするJavaScriptアプリ」のような本を読んで写経するといいかもしれません。そのうち Typescript に慣れていくと、今度は Javascript でちょっと込み入った何かを書こうとすると、型チェックをしてくれていないのがかなり心もとない気がしてくると思います。

投稿2022/10/29 17:10

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自己解決

理由はよくわかりませんが、contentに対するreplaceだと動きました

投稿2022/10/29 16:58

snafkin999

総合スコア27

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問