Skip to content

MapInto Method ​

The mapInto() method creates a collection of new class instances by mapping each item into the specified class. This is particularly useful when you need to transform raw data into class instances.

Basic Syntax ​

typescript
collect(items).mapInto(constructor: new (...args: any[]) => T)

Examples ​

Basic Usage ​

typescript
import { collect } from 'ts-collect'

class User {
  constructor(public name: string, public email: string) {}

  getFullInfo(): string {
    return `${this.name} (${this.email})`
  }
}

const users = collect([
  { name: 'John Doe', email: 'john@example.com' },
  { name: 'Jane Smith', email: 'jane@example.com' }
]).mapInto(User)

users.each((user) => {
  console.log(user.getFullInfo())
})

// Output:
// "John Doe (john@example.com)"
// "Jane Smith (jane@example.com)"

Working with Complex Classes ​

typescript
class Product {
  public id: number
  public name: string
  public price: number

  constructor(data: any) {
    this.id = data.id
    this.name = data.name
    this.price = data.price
  }

  getFormattedPrice(): string {
    return `$${this.price.toFixed(2)}`
  }

  applyDiscount(percentage: number): void {
    this.price = this.price * (1 - percentage / 100)
  }
}

const products = collect([
  { id: 1, name: 'Laptop', price: 999.99 },
  { id: 2, name: 'Mouse', price: 49.99 }
]).mapInto(Product)

products.each((product) => {
  product.applyDiscount(10)
  console.log(`${product.name}: ${product.getFormattedPrice()}`)
})

Real-world Examples ​

Data Transfer Objects (DTOs) ​

typescript
class UserDTO {
  public id: number
  public fullName: string
  public email: string
  private roles: string[]

  constructor(data: any) {
    this.id = data.id
    this.fullName = `${data.firstName} ${data.lastName}`.trim()
    this.email = data.email.toLowerCase()
    this.roles = data.roles || []
  }

  hasRole(role: string): boolean {
    return this.roles.includes(role)
  }

  isAdmin(): boolean {
    return this.hasRole('admin')
  }
}

// Raw data from API
const rawUsers = [
  { id: 1, firstName: 'John', lastName: 'Doe', email: 'JOHN@example.com', roles: ['user'] },
  { id: 2, firstName: 'Jane', lastName: 'Smith', email: 'JANE@example.com', roles: ['admin', 'user'] }
]

const userDtos = collect(rawUsers).mapInto(UserDTO)

userDtos.each((user) => {
  console.log(`${user.fullName} is admin: ${user.isAdmin()}`)
})

Entity Mapping ​

typescript
class OrderItem {
  constructor(
    public productId: number,
    public quantity: number,
    public unitPrice: number
  ) {}

  getTotalPrice(): number {
    return this.quantity * this.unitPrice
  }
}

class Order {
  public id: number
  public customerId: number
  public items: OrderItem[]

  constructor(data: any) {
    this.id = data.id
    this.customerId = data.customerId
    this.items = collect(data.items).mapInto(OrderItem).all()
  }

  getTotalAmount(): number {
    return collect(this.items)
      .sum(item => item.getTotalPrice())
  }
}

const rawOrders = [
  {
    id: 1,
    customerId: 101,
    items: [
      { productId: 1, quantity: 2, unitPrice: 10 },
      { productId: 2, quantity: 1, unitPrice: 20 }
    ]
  }
]

const orders = collect(rawOrders).mapInto(Order)
orders.each((order) => {
  console.log(`Order #${order.id} total: $${order.getTotalAmount()}`)
})

Advanced Usage ​

With Validation ​

typescript
class ValidatedUser {
  private _email: string
  private _age: number

  constructor(data: any) {
    this.validateData(data)
    this._email = data.email
    this._age = data.age
  }

  private validateData(data: any): void {
    if (!data.email || !data.email.includes('@')) {
      throw new Error('Invalid email')
    }
    if (!data.age || data.age < 0) {
      throw new Error('Invalid age')
    }
  }

  get email(): string { return this._email }
  get age(): number { return this._age }
}

try {
  const users = collect([
    { email: 'valid@example.com', age: 25 },
    { email: 'invalid', age: -1 }
  ]).mapInto(ValidatedUser)
}
catch (error) {
  console.error('Validation failed:', error.message)
}

Type Safety ​

typescript
interface IEntity {
  id: number
  created: Date
}

class BaseEntity implements IEntity {
  public id: number
  public created: Date

  constructor(data: any) {
    this.id = data.id
    this.created = new Date(data.created)
  }
}

class TypedUser extends BaseEntity {
  public name: string
  public email: string

  constructor(data: any) {
    super(data)
    this.name = data.name
    this.email = data.email
  }
}

const typedUsers = collect<Partial<TypedUser>>([
  { id: 1, name: 'John', email: 'john@example.com', created: '2024-01-01' }
]).mapInto(TypedUser)

// TypeScript ensures type safety
typedUsers.each((user) => {
  const date: Date = user.created // ✓ Valid
  const name: string = user.name // ✓ Valid
  // const invalid = user.nonexistent // ✗ TypeScript error
})

Return Value ​

  • Returns a new Collection instance containing instances of the specified class
  • Each item in the collection will be an instance of the provided constructor
  • Maintains type safety when used with TypeScript classes and interfaces

Released under the MIT License.