Skip to content

Commit a1b5a97

Browse files
r4aijacktuck
andauthoredFeb 13, 2024··
feat: Improve type inference for oEmbed type in TypeScript (#113)
Co-authored-by: jack <8209433+jacktuck@users.noreply.github.com>
1 parent b80b800 commit a1b5a97

File tree

3 files changed

+105
-43
lines changed

3 files changed

+105
-43
lines changed
 

‎README.md

+44-15
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,7 @@ type Metadata = {
5858
author?: string
5959
theme_color?: string
6060
canonical_url?: string
61-
oEmbed?: {
62-
type: 'photo' | 'video' | 'link' | 'rich'
63-
version?: string
64-
title?: string
65-
author_name?: string
66-
author_url?: string
67-
provider_name?: string
68-
provider_url?: string
69-
cache_age?: number
70-
thumbnails?: [{
71-
url?: string
72-
width?: number
73-
height?: number
74-
}]
75-
}
61+
oEmbed?: OEmbedPhoto | OEmbedVideo | OEmbedLink | OEmbedRich
7662
twitter_card: {
7763
card: string
7864
site?: string
@@ -147,6 +133,49 @@ type Metadata = {
147133
}
148134
}
149135
}
136+
137+
type OEmbedBase = {
138+
type: "photo" | "video" | "link" | "rich"
139+
version: string
140+
title?: string
141+
author_name?: string
142+
author_url?: string
143+
provider_name?: string
144+
provider_url?: string
145+
cache_age?: number
146+
thumbnails?: [
147+
{
148+
url?: string
149+
width?: number
150+
height?: number
151+
}
152+
]
153+
}
154+
155+
type OEmbedPhoto = OEmbedBase & {
156+
type: "photo"
157+
url: string
158+
width: number
159+
height: number
160+
}
161+
162+
type OEmbedVideo = OEmbedBase & {
163+
type: "video"
164+
html: string
165+
width: number
166+
height: number
167+
}
168+
169+
type OEmbedLink = OEmbedBase & {
170+
type: "link"
171+
}
172+
173+
type OEmbedRich = OEmbedBase & {
174+
type: "rich"
175+
html: string
176+
width: number
177+
height: number
178+
}
150179
```
151180
152181
## The who 💖

‎src/types.ts

+44-19
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,7 @@ export type Metadata = {
2424
author?: string;
2525
theme_color?: string;
2626
canonical_url?: string;
27-
oEmbed?: {
28-
type: "photo" | "video" | "link" | "rich";
29-
width?: number;
30-
height?: number;
31-
version?: string;
32-
title?: string;
33-
author_name?: string;
34-
author_url?: string;
35-
provider_name?: string;
36-
provider_url?: string;
37-
cache_age?: number;
38-
thumbnails?: [
39-
{
40-
url?: string;
41-
width?: number;
42-
height?: number;
43-
}
44-
];
45-
};
27+
oEmbed?: OEmbedPhoto | OEmbedVideo | OEmbedLink | OEmbedRich;
4628
twitter_card: {
4729
card: string;
4830
site?: string;
@@ -117,3 +99,46 @@ export type Metadata = {
11799
};
118100
};
119101
};
102+
103+
type OEmbedBase = {
104+
type: "photo" | "video" | "link" | "rich";
105+
version: string;
106+
title?: string;
107+
author_name?: string;
108+
author_url?: string;
109+
provider_name?: string;
110+
provider_url?: string;
111+
cache_age?: number;
112+
thumbnails?: [
113+
{
114+
url?: string;
115+
width?: number;
116+
height?: number;
117+
}
118+
];
119+
};
120+
121+
type OEmbedPhoto = OEmbedBase & {
122+
type: "photo";
123+
url: string;
124+
width: number;
125+
height: number;
126+
};
127+
128+
type OEmbedVideo = OEmbedBase & {
129+
type: "video";
130+
html: string;
131+
width: number;
132+
height: number;
133+
};
134+
135+
type OEmbedLink = OEmbedBase & {
136+
type: "link";
137+
};
138+
139+
type OEmbedRich = OEmbedBase & {
140+
type: "rich";
141+
html: string;
142+
width: number;
143+
height: number;
144+
};

‎test/oembed/test.ts

+17-9
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@ test("width/height should be numbers", async () => {
3232

3333
const result = await unfurl("http://localhost/html/oembed");
3434

35-
expect(result.oEmbed.width).toEqual(640);
36-
expect(result.oEmbed.height).toEqual(640);
35+
expect(result.oEmbed?.type).toEqual("video");
36+
const oEmbed =
37+
result.oEmbed?.type === "video" ? result.oEmbed : (result.oEmbed as never);
3738

38-
expect(result.oEmbed.thumbnails[0].width).toEqual(200);
39-
expect(result.oEmbed.thumbnails[0].height).toEqual(200);
39+
expect(oEmbed.width).toEqual(640);
40+
expect(oEmbed.height).toEqual(640);
41+
42+
expect(oEmbed.thumbnails?.[0].width).toEqual(200);
43+
expect(oEmbed.thumbnails?.[0].height).toEqual(200);
4044
});
4145

4246
test("should decode entities in OEmbed URL", async () => {
@@ -54,11 +58,15 @@ test("should decode entities in OEmbed URL", async () => {
5458

5559
const result = await unfurl("http://localhost/html/oembed");
5660

57-
expect(result.oEmbed.width).toEqual(640);
58-
expect(result.oEmbed.height).toEqual(640);
61+
expect(result.oEmbed?.type).toEqual("video");
62+
const oEmbed =
63+
result.oEmbed?.type === "video" ? result.oEmbed : (result.oEmbed as never);
64+
65+
expect(oEmbed.width).toEqual(640);
66+
expect(oEmbed.height).toEqual(640);
5967

60-
expect(result.oEmbed.thumbnails[0].width).toEqual(200);
61-
expect(result.oEmbed.thumbnails[0].height).toEqual(200);
68+
expect(oEmbed.thumbnails?.[0].width).toEqual(200);
69+
expect(oEmbed.thumbnails?.[0].height).toEqual(200);
6270
});
6371

6472
test("should prefer fetching JSON oEmbed", async () => {
@@ -118,7 +126,7 @@ test("should upgrade to HTTPS if needed", async () => {
118126

119127
const result = await unfurl("http://localhost/html/oembed-http");
120128

121-
expect(result.oEmbed.version).toEqual("1.0");
129+
expect(result.oEmbed?.version).toEqual("1.0");
122130
});
123131

124132
test("should build oEmbed from JSON", async () => {

0 commit comments

Comments
 (0)
Please sign in to comment.