Skip to content

Working with TypeScript ​

Feedsmith is built with TypeScript and provides comprehensive type definitions for all feed formats and namespaces.

Importing Types ​

All types are available through the main feedsmith export:

typescript
import type { RssFeed, AtomFeed, JsonFeed, RdfFeed, Opml } from 'feedsmith'

Each namespace contains the complete type system for that format:

typescript
// RSS types
type Feed = RssFeed.Feed<string>
type Item = RssFeed.Item<string>
type Category = RssFeed.Category
type Enclosure = RssFeed.Enclosure

// Atom types
type Entry = AtomFeed.Entry<string>
type Link = AtomFeed.Link<string>

// JSON Feed types
type JsonItem = JsonFeed.Item<string>
type Author = JsonFeed.Author

// RDF types
type RdfItem = RdfFeed.Item<string>

// OPML types
type Document = Opml.Document<string>
type Outline = Opml.Outline<string>

Using Types with Parsing ​

When parsing, dates are returned as strings. Use <string> for the generic parameter:

typescript
import { type RssFeed, parseRssFeed } from 'feedsmith'

const feed: RssFeed.Feed<string> = parseRssFeed(xmlContent)

// Access properties with full type safety
feed.title // string | undefined
feed.pubDate // string | undefined
feed.items?.[0]?.enclosures // Enclosure[] | undefined

NOTE

Explicit typing is usually not required when parsing since the parse functions already return properly typed objects. TypeScript will automatically infer the correct types.

Using Types with Generating ​

When generating, you can use Date objects. Use <Date> for the generic parameter:

typescript
import { type RssFeed, generateRssFeed } from 'feedsmith'

const feed: RssFeed.Feed<Date> = {
  title: 'My Podcast',
  link: 'https://example.com',
  description: 'A great podcast',
  pubDate: new Date(),
  items: [{
    title: 'Episode 1',
    description: 'First episode',
    enclosures: [{
      url: 'https://example.com/ep1.mp3',
      length: 12345678,
      type: 'audio/mpeg'
    }]
  }]
}

const xml = generateRssFeed(feed)

Universal Parser Return Type ​

The universal parseFeed function returns a discriminated union typed as AnyFeed:

typescript
import { type AnyFeed, parseFeed } from 'feedsmith'

const result: AnyFeed = parseFeed(content)

if (result.format === 'rss') {
  result.feed // RssFeed.Feed<string>
} else if (result.format === 'atom') {
  result.feed // AtomFeed.Feed<string>
}

Importing Namespace Types ​

All namespace types are exported from the main package, allowing direct type access:

typescript
import type { ItunesNs, DcNs, MediaNs, PodcastNs } from 'feedsmith'

Each namespace contains its complete type system:

typescript
// Dublin Core namespace types
type DcFeed = DcNs.Feed
type DcItem = DcNs.Item

// Media namespace types
type MediaFeed = MediaNs.Feed
type MediaItem = MediaNs.Item
type MediaContent = MediaNs.Content
type MediaGroup = MediaNs.Group

This is useful when you need to type variables or function parameters with namespace-specific types:

typescript
import type { ItunesNs, PodcastNs } from 'feedsmith'
import { generateRssFeed } from 'feedsmith'

const itunesCategory: ItunesNs.Category = {
  text: 'Technology',
  categories: [{ text: 'Software How-To' }]
}

const transcript: PodcastNs.Transcript = {
  url: 'https://example.com/transcript.srt',
  type: 'application/srt'
}

const xml = generateRssFeed({
  title: 'My Podcast',
  itunes: {
    categories: [itunesCategory]
  },
  items: [{
    title: 'Episode 1',
    podcast: {
      transcripts: [transcript]
    }
  }]
})

Each namespace's type export name can be found in the "Types" section of its reference documentation.

Complete Example ​

Here's an example on how you can utilize the types for sub-elements of the RSS feed while generating a podcast feed:

typescript
import { type RssFeed, generateRssFeed } from 'feedsmith'

const items: Array<RssFeed.Item<Date>> = [{
  title: 'Episode 1: Introduction',
  description: 'Getting started with TypeScript',
  pubDate: new Date('2024-01-15T10:00:00Z'),
  enclosures: [{
    url: 'https://mypodcast.com/ep1.mp3',
    length: 45678901,
    type: 'audio/mpeg'
  }],
  itunes: {
    duration: '01:15:30',
    episode: 1,
    explicit: false
  }
}]

const feed: RssFeed.Feed<Date> = {
  title: 'My TypeScript Podcast',
  link: 'https://mypodcast.com',
  description: 'A podcast about TypeScript',
  language: 'en-us',
  pubDate: new Date(),
  itunes: {
    author: 'John Doe',
    owner: {
      name: 'John Doe',
      email: '[email protected]'
    },
    image: 'https://mypodcast.com/artwork.jpg',
    category: [{ name: 'Technology' }],
    explicit: false
  },
  items
}

const xml = generateRssFeed(feed)

The TDate Parameter ​

The TDate generic parameter indicates how dates are represented in the typed objects. This differentiation is needed as Feedsmith intentionally does not parse dates (see Handling Dates).

In general, use:

  • Type<string> when parsing
  • Type<Date> when generating
typescript
// Parsing - dates are strings
const parsed: RssFeed.Feed<string> = parseRssFeed(xml)

// Generating - dates are Date objects
const generated: RssFeed.Feed<Date> = {
  title: 'Feed',
  link: 'https://example.com',
  description: 'Description',
  pubDate: new Date(), // Must be Date
  items: []
}

The TStrict Parameter ​

The TStrict generic parameter controls whether specification-required fields are enforced at compile time. When you pass { strict: true } to generate functions, TypeScript uses the strict variant of the type, making required fields mandatory.

See Strict Mode for usage details.

Requirable Markers ​

In type definitions, fields wrapped in Requirable<T> become mandatory when strict mode is enabled:

typescript
// Type definition (simplified)
type Enclosure<TStrict> = Strict<{
  url: Requirable<string>     // Required in strict mode
  length: Requirable<number>  // Required in strict mode
  type: Requirable<string>    // Required in strict mode
}, TStrict>

Look for Requirable<...> in reference documentation to identify which fields become required in strict mode.