Guides

TypeScript integration

stardew-valley-data ships with complete TypeScript declarations -- every function, type, and interface is fully typed with no additional packages required.


Importing types

All types are exported from the main entry point. Use import type when you only need the type for annotations:

import type { Crop, Fish, Villager, Season, Quality } from 'stardew-valley-data'

You can also import types alongside runtime values:

import { crops, type Crop, type Season } from 'stardew-valley-data'

function getCropsBySeason(season: Season): Crop[] {
  return crops().bySeason(season).get()
}

Common shared types

Several types are shared across multiple modules. These are defined in the common type module and re-exported from the main package.

Season

type Season = 'spring' | 'summer' | 'fall' | 'winter' | 'ginger island'

Used by crops, fish, trees, villager birthdays, and more. Note that 'ginger island' is included as a season for items available year-round on the island.

Quality

type Quality = 'silver' | 'gold' | 'iridium'

Used by the quality calculator and anywhere item quality tiers apply.

EnergyHealth

interface EnergyHealth {
  energy?: number
  health?: number
  poison?: boolean
}

Represents the energy and health values of consumable items. Present on crops, fish, cooking recipes, and other edible items.

SeedBuyPrice

interface SeedBuyPrice {
  place: string
  price: number
}

Represents a purchase location and cost for seeds or saplings.

Ingredient

interface Ingredient {
  name: string
  id: string
  quantity: number
}

Represents a crafting or cooking recipe ingredient with its required quantity.

Stage

interface Stage {
  name: string
  image: string
}

Represents a growth stage for crops and trees, with an associated image path.

GiftPreferences

interface GiftPreferences {
  loves: string[]
  likes: string[]
  neutrals: string[]
  dislikes: string[]
  hates: string[]
}

Gift preference lists used by villagers and universal gift data.


Union types

Several modules use discriminated unions to represent items with different shapes. The discriminant is always the type field.

Animal

type Animal = Pet | FarmAnimal

Where:

interface Pet {
  type: 'pet'
  id: string
  name: string
  variant?: number
  image: string
}

interface FarmAnimal {
  type: 'farm-animal'
  id: string
  name: string
  description: string
  building: string
  purchasePrice: number | null
  sellPrice: number
  daysToMature: number
  daysToProduce: number
  harvestMethod: 'drop' | 'tool' | 'dig'
  harvestTool: string | null
  produce: AnimalProduce
  deluxeProduce: AnimalProduce | null
  image: string
}

Tree

type Tree = FruitTree | WildTree

Where FruitTree has type: 'fruit-tree' with produce and sapling data, and WildTree has type: 'wild-tree' with seed and tapper data.


Type guards

The package exports type guard functions for narrowing union types. These are standard TypeScript type predicates that work with if statements, filter(), and anywhere else TypeScript narrows types.

isPet / isFarmAnimal

import { animals, isPet, isFarmAnimal } from 'stardew-valley-data'

const allAnimals = animals().get()

for (const animal of allAnimals) {
  if (isPet(animal)) {
    // TypeScript knows `animal` is Pet here
    console.log(`Pet: ${animal.name}`)
  }

  if (isFarmAnimal(animal)) {
    // TypeScript knows `animal` is FarmAnimal here
    console.log(`${animal.name} produces ${animal.produce.name}`)
    console.log(`Lives in: ${animal.building}`)
  }
}

Type guards also work with Array.filter():

import { animals, isFarmAnimal } from 'stardew-valley-data'

// TypeScript infers FarmAnimal[] -- no cast needed
const farmAnimals = animals().get().filter(isFarmAnimal)

Using generics with QueryBase

The QueryBase<T> class is generic over any type T that has id: string and name: string. This means all terminal methods are fully typed:

import { crops } from 'stardew-valley-data'

// crops() returns CropQuery which extends QueryBase<Crop>
const result = crops().bySeason('summer').get() // Crop[]
const first = crops().first() // Crop | undefined
const found = crops().find('248') // Crop | undefined
const byName = crops().findByName('Melon') // Crop | undefined
const count = crops().count() // number

When you pass custom source data to a factory function, the types flow through automatically:

import { crops, type Crop } from 'stardew-valley-data'

const customData: Crop[] = [
  /* your data */
]
const query = crops(customData) // CropQuery (extends QueryBase<Crop>)
const results = query.get() // Crop[]

Typing function parameters

Use the exported types to write strongly-typed functions:

import { crops, type Crop, type Season } from 'stardew-valley-data'

function getMostValuableCrop(season: Season): Crop | undefined {
  return crops().bySeason(season).sortBySellPrice('desc').first()
}

function formatCrop(crop: Crop): string {
  const seasons = crop.seasons.join(', ')
  const regrow = crop.regrowDays ? ` (regrows in ${crop.regrowDays}d)` : ''
  return `${crop.name}: ${crop.cropSellPrice}g${regrow} [${seasons}]`
}

Working with search results

import {
  search,
  type SearchResult,
  type SearchResultKind,
} from 'stardew-valley-data'

function findItems(query: string, kind?: SearchResultKind): SearchResult[] {
  return kind ? search(query, [kind]) : search(query)
}

const results = findItems('Melon', 'crop')
results.forEach((r) => {
  console.log(`[${r.kind}] ${r.name} - ${r.sellPrice ?? 'N/A'}g`)
})

Working with calculator results

import {
  qualityCalculator,
  type QualityPrice,
  type QualityEnergyHealth,
} from 'stardew-valley-data'

const calc = qualityCalculator()
const prices: QualityPrice[] = calc.sellPrices(250)
const stats: QualityEnergyHealth[] = calc.energyHealth(113, 50)

Module-specific types

Each module exports its own types. Here are some commonly used ones:

ModuleKey types
CropsCrop, HarvestQuantity
FishFish, FishCatchType, FishWeather
VillagersVillager
AnimalsAnimal, Pet, FarmAnimal, AnimalProduce
TreesTree, FruitTree, WildTree, FruitTreeProduce, WildTreeTapper
SearchSearchResult, SearchResultKind
CalculatorQualityPrice, QualityEnergyHealth
Save fileSaveData, SavePlayer, SaveFarm, SaveDate, and 30+ more
SeasonsSeasonData, Festival
CommonSeason, Quality, EnergyHealth, SeedBuyPrice, Ingredient, Stage, GiftPreferences

All types are importable from the main 'stardew-valley-data' entry point.


Next steps

Previous
Query builder basics