Imports & Exports
Atscript imports and exports work similar to TypeScript with some specific limitations and rules.
Key Limitations
- No default imports/exports - Only named exports and imports are supported
- No namespace or rename syntax - No
import * as,export * as, orimport { a as b } .asfiles can only import.asfiles - Cannot import files from the target language
Named Exports
// user.as - Named exports only
export interface User {
id: string
name: string
}
export type UserID = string
export type Status = 'active' | 'inactive'
// Private (not exported)
interface InternalConfig {
debug: boolean
}Importing in .as Files
In .as files, omit the file extension:
// app.as
import { User, UserID, Status } from './user'
import { Product } from '../models/product'
export interface Order {
user: User
items: Product[]
}Valid Import/Export Examples
Basic Named Import/Export
// types.as
export interface Person {
name: string
}
export type ID = string// main.as
import { Person, ID } from './types'
export interface Employee extends Person {
employeeId: ID
}Multiple Imports from Same File
// models.as
export interface User { }
export interface Product { }
export interface Order { }
export type Status = string// app.as
import { User, Product, Order, Status } from './models'Nested Directory Imports
// domain/user.as
import { BaseEntity } from '../shared/base'
import { Address } from './types/address'Importing from Packages (node_modules)
Atscript supports importing .as files published in npm packages. Use bare specifiers (no ./ prefix) to import from node_modules:
// app.as
import { User } from 'my-lib/user'
import { Product } from '@my-org/models/product'Like relative imports, the .as extension is omitted. The resolver automatically appends it.
How Resolution Works
When Atscript encounters a bare import specifier (one that doesn't start with . or /):
The specifier is parsed into a package name and subpath:
my-lib/user→ packagemy-lib, subpath./user.as@my-org/models/product→ package@my-org/models, subpath./product.as
The resolver walks up from the importing file's directory, checking for
node_modules/<package>/package.jsonat each level.If found, it checks the
exportsfield for a matching subpath entry with theatscriptcondition (pointing to the raw.assource file).If no
exportsmatch, it falls back to looking for the file directly atnode_modules/<package>/<subpath>.as.
Publishing Packages with .as Files
To publish a package that exports .as files, declare them in package.json using the standard exports field with an "atscript" condition:
{
"name": "@my-org/models",
"exports": {
"./user.as": {
"atscript": "./src/user.as",
"types": "./dist/user.as.d.ts",
"import": "./dist/user.as.mjs"
},
"./product.as": {
"atscript": "./src/product.as",
"types": "./dist/product.as.d.ts",
"import": "./dist/product.as.mjs"
}
}
}atscript— points to the raw.assource (used by the Atscript compiler and LSP)types— TypeScript declarations (generated byasc -f dts)import— compiled JavaScript (generated byasc -f js)
For packages with many .as files, use wildcard patterns:
{
"exports": {
"./*.as": {
"atscript": "./src/*.as",
"types": "./dist/*.as.d.ts",
"import": "./dist/*.as.mjs"
}
}
}Simplest option: If your .as files are at the expected path, no exports configuration is needed. The resolver falls back to direct file access:
node_modules/@my-org/models/
user.as ← import { User } from '@my-org/models/user'
product.as ← import { Product } from '@my-org/models/product'
package.json ← no exports field neededInvalid Syntax (Not Supported)
// ❌ Default exports
export default interface User { }
// ❌ Default imports
import User from './user'
// ❌ Namespace imports
import * as models from './models'
// ❌ Export namespace
export * as utils from './utils'
// ❌ Import with rename
import { User as UserModel } from './user'
// ❌ Re-exports
export { User } from './user'
// ❌ Importing non-.as files
import { helper } from './helper.ts'Importing .as Files in TypeScript
TypeScript files must include the .as extension:
// app.ts
import { User, UserID, Status } from './user.as'
import { Product } from '../models/product.as'
// Use as both type and runtime object
const user: User = { id: '1', name: 'John' }
const validator = User.validator()
const metadata = User.metadataImporting from Packages in TypeScript
When importing .as types from an npm package in TypeScript, use the .as extension (added automatically by the Atscript compiler when generating .js/.d.ts output):
// app.ts — importing .as types from a published package
import { User } from '@my-org/models/user.as'
import { Product } from 'shared-types/product.as'The bundler (unplugin-atscript) and TypeScript resolve these through the package's exports field:
- Bundlers use the
"import"condition to find the compiled.as.mjs/.as.js - TypeScript uses the
"types"condition to find the.as.d.tsdeclarations
If the package doesn't use exports, bundlers resolve the .as file directly from node_modules and compile it on the fly via the unplugin load() hook.
Setup for TypeScript Integration
For TypeScript to import .as files:
- With VSCode Extension: Automatically generates
.as.d.tsfiles on save - With CLI: Run
asc -f dtsto generate TypeScript definitions - With Bundler: Use
unplugin-atscriptfor automatic compilation
Example generated structure:
src/
user.as # Source file
user.as.js # Generated JavaScript (with asc -f js)
user.as.d.ts # Generated TypeScript definitions
app.ts # Can import from './user.as'Next Steps
- Primitives — Primitive types and extensions
- Annotations — Metadata system