Skip to content
svead

Leveraging schema-dts Type Safety

Svead uses schema-dts which provides TypeScript types for all 800+ Schema.org types. Here’s how to leverage it effectively:

Type-Safe Schema Creation

Get full autocomplete and type checking:

TypeScript
1import type { BlogPosting, Person, Organization } from 'schema-dts';
2import type { SchemaOrgProps } from 'svead';
3
4// Strongly typed - autocomplete available for all properties
5const author: Person = {
6	'@type': 'Person',
7	name: 'John Doe',
8	url: 'https://example.com/author/john',
9	sameAs: [
10		'https://twitter.com/johndoe',
11		'https://github.com/johndoe',
12	],
13	jobTitle: 'Developer', // Autocomplete knows valid properties
14};
15
16const blog_post: BlogPosting = {
17	'@type': 'BlogPosting',
18	headline: 'My Blog Post',
19	author: author, // Type-safe nesting
20	datePublished: '2023-08-22T10:00:00Z',
21	// TypeScript will error on invalid properties
22};
23
24const schema: SchemaOrgProps['schema'] = blog_post;

Reusable Typed Schemas

Create reusable, type-safe schema fragments:

TypeScript
1import type { Person, Organization, ImageObject } from 'schema-dts';
2
3// Typed person schema
4const create_person = (name: string, url: string): Person => ({
5	'@type': 'Person',
6	name,
7	url,
8	sameAs: [
9		`https://twitter.com/${name.toLowerCase()}`,
10		`https://github.com/${name.toLowerCase()}`,
11	],
12});
13
14// Typed organization schema
15const create_organization = (
16	name: string,
17	url: string,
18): Organization => ({
19	'@type': 'Organization',
20	name,
21	url,
22	logo: {
23		'@type': 'ImageObject',
24		url: `${url}/logo.png`,
25	},
26});
27
28// Use in schemas with type safety
29const schema: SchemaOrgProps['schema'] = {
30	'@type': 'BlogPosting',
31	headline: 'Article',
32	author: create_person('John Doe', 'https://example.com'),
33	publisher: create_organization('Example', 'https://example.com'),
34};

Union Types for Flexible Schemas

schema-dts supports union types for properties that accept multiple types:

TypeScript
1import type { BlogPosting, Person, Organization } from 'schema-dts';
2
3// author can be Person, Organization, or array of either
4const schema: BlogPosting = {
5	'@type': 'BlogPosting',
6	headline: 'Article',
7	// Single person
8	author: {
9		'@type': 'Person',
10		name: 'John',
11	},
12	// Or organization
13	// author: {
14	//   '@type': 'Organization',
15	//   name: 'Company'
16	// },
17	// Or array of authors
18	// author: [
19	//   { '@type': 'Person', name: 'John' },
20	//   { '@type': 'Person', name: 'Jane' }
21	// ]
22};

Array Schemas with Type Safety

When using arrays, schema-dts maintains type safety:

TypeScript
1import type { ItemList, ListItem } from 'schema-dts';
2
3const item_list: ItemList = {
4	'@type': 'ItemList',
5	itemListElement: [
6		{
7			'@type': 'ListItem',
8			position: 1,
9			item: {
10				'@type': 'Product',
11				name: 'Product 1',
12			},
13		},
14		{
15			'@type': 'ListItem',
16			position: 2,
17			item: {
18				'@type': 'Product',
19				name: 'Product 2',
20			},
21		},
22	],
23};

Complex Nested Schemas

schema-dts handles deep nesting with full type safety:

TypeScript
1import type {
2	Recipe,
3	HowToStep,
4	NutritionInformation,
5} from 'schema-dts';
6
7const recipe: Recipe = {
8	'@type': 'Recipe',
9	name: 'Chocolate Cake',
10	recipeIngredient: ['flour', 'sugar', 'cocoa'],
11	recipeInstructions: [
12		{
13			'@type': 'HowToStep',
14			name: 'Mix ingredients',
15			text: 'Mix all ingredients together',
16			image: 'https://example.com/step1.jpg',
17		},
18		{
19			'@type': 'HowToStep',
20			name: 'Bake',
21			text: 'Bake at 350°F for 30 minutes',
22		},
23	],
24	nutrition: {
25		'@type': 'NutritionInformation',
26		calories: '350 calories',
27		fatContent: '12g',
28		proteinContent: '5g',
29	},
30	aggregateRating: {
31		'@type': 'AggregateRating',
32		ratingValue: '4.8',
33		reviewCount: '124',
34	},
35};

Using WithContext Type

schema-dts provides WithContext<T> to include @context:

TypeScript
1import type { WithContext, BlogPosting } from 'schema-dts';
2
3// This type includes @context automatically
4const schema: WithContext<BlogPosting> = {
5	'@context': 'https://schema.org',
6	'@type': 'BlogPosting',
7	headline: 'Article',
8};
9
10// SchemaOrg component adds @context if missing, so this is optional

Type Guards and Validation

Use TypeScript to validate schema structure:

TypeScript
1import type { Thing } from 'schema-dts';
2
3// Function that only accepts valid Thing types
4function validate_schema(schema: Thing): boolean {
5	// TypeScript ensures schema has correct structure
6	return !!schema['@type'];
7}
8
9// Type-safe schema manipulation
10const schema: Thing = {
11	'@type': 'BlogPosting',
12	headline: 'Title',
13};
14
15if (validate_schema(schema)) {
16	// Safe to use
17}

Importing Specific Types

Import only what you need for better tree-shaking:

TypeScript
1// Import specific types
2import type {
3	BlogPosting,
4	Person,
5	Organization,
6	ImageObject,
7	BreadcrumbList,
8	ListItem,
9} from 'schema-dts';
10
11// Instead of importing everything
12// import type { Thing } from 'schema-dts';

Common Type Patterns

Frequently used type combinations:

TypeScript
1import type {
2	BlogPosting,
3	Person,
4	Organization,
5	ImageObject,
6} from 'schema-dts';
7
8// Author (can be Person or Organization)
9type Author = Person | Organization;
10
11// Image (can be string URL or ImageObject)
12type Image = string | ImageObject | ImageObject[];
13
14// Reusable function with types
15function create_blog_post(
16	headline: string,
17	author: Author,
18	image?: Image,
19): BlogPosting {
20	return {
21		'@type': 'BlogPosting',
22		headline,
23		author,
24		...(image && { image }),
25		datePublished: new Date().toISOString(),
26	};
27}
28
29// Type-safe usage
30const post = create_blog_post(
31	'My Post',
32	{ '@type': 'Person', name: 'John' },
33	'https://example.com/image.jpg',
34);

Catching Errors at Compile Time

schema-dts catches errors before runtime:

TypeScript
1import type { BlogPosting } from 'schema-dts';
2
3const schema: BlogPosting = {
4	'@type': 'BlogPosting',
5	headline: 'Title',
6	// ❌ TypeScript error: 'invalidProperty' doesn't exist on BlogPosting
7	// invalidProperty: 'value',
8
9	// ❌ TypeScript error: wrong type
10	// datePublished: 123,
11
12	// ✅ Correct
13	datePublished: '2023-08-22T10:00:00Z',
14};

Extending Schemas with Custom Properties

While schema-dts is strict, you can add custom properties:

TypeScript
1import type { BlogPosting } from 'schema-dts';
2
3// Extend with custom properties if needed
4interface CustomBlogPosting extends BlogPosting {
5	customField?: string;
6}
7
8const schema: CustomBlogPosting = {
9	'@type': 'BlogPosting',
10	headline: 'Title',
11	customField: 'Custom data',
12};
13
14// Note: Custom properties won't validate with Schema.org validators
All documentation