Home > Software engineering >  Typescript Generic chained function to Swift
Typescript Generic chained function to Swift

Time:11-03

I'm really struggling to comprehend how to (if even possible) to convert a generics function written in Typescript into something I can use in Swift.

export type Filter<T> = (value: T) => boolean

export function isKeyEqualToValue<T>(key: keyof T) {
  return function (value: T[keyof T]): Filter<T> {
    return (object: T) => object[key] === value
  }
}
isKeyEqualToValue<T>('key')(someObject.key)
const filters = userFilters.map(userFilterSet => isEvery(buildAlertFilter(userFilterSet)))
  const isMatch = isAny(filters)

  return flow.reduce((feed: String[], obj: SomeType) => {
    if (!isMatch(obj)) return feed

    return [
      ...feed,
      {
         ...obj 
      },
    ]
  }, [])
}

I would like to be able to input a struct model in for T and check if the inputted value matches the key. Would greatly appreciate some guidance here!

EDIT:

I've added how the method is being called and used. Essentially I'm trying to avoid doing an algorithm O(n)^2 and so I'm trying to build a list of filters based on our user's choice. Then cross check the bulk of my data (SomeType) with those built filters.

I'm working to translate another function using the similar principles.

export function hasInArray<T>(key: keyof T) {
  return function (values: Array<any>): Filter<T> {
    return (object: T) => values.includes((object[key] as unknown) as string)
  }
}

This is what I have so far.

func notInArray<Root, Value>(for keyPath: KeyPath<Root, Value>) -> (Array<Any>) -> Filter<Root, Value> {
    { values in { object in !values.contains(where: object[keyPath: keyPath]) } } }

CodePudding user response:

You haven't given how you expect to use this, so I need to make some assumptions. I'm assuming the TypeScript that calls this looks like this:

interface Person {
  name: string;
  age: number;
}

const key: keyof Person = "name";
const nameTester = isKeyEqualToValue(key);
const person = {name: "Alice", age: 23};
const result = nameTester("Alice")(person);

The equivalent to TypeScript's keyof in Swift is KeyPath. Keeping this as close to the TypeScript syntax as possible to make it easier to see how it maps, this would look like:

typealias Filter<T> = (_ value: T) -> Bool

func isKeyEqualToValue<T, Value>(key: KeyPath<T, Value>) -> (Value) -> (T) -> Bool
where Value: Equatable
{
    return { (value: Value) -> Filter<T> in
        return { (object: T) in object[keyPath: key] == value }
    }
}

struct Person: Equatable {
    var name: String
    var age: Int
}

let key = \Person.name
let nameTester = isKeyEqualToValue(key: key)
let person = Person(name: "Alice", age: 23)
let result = nameTester("Alice")(person)

To make it better Swift (rather than matching the TypeScript so closely), it would look like:

typealias Filter<Root, Value: Equatable> = (Value) -> (Root) -> Bool

func isEqualToValue<Root, Value>(for keyPath: KeyPath<Root, Value>) -> Filter<Root, Value>
{
    { value in { object in object[keyPath: keyPath] == value } }
}

let nameTester = isEqualToValue(for: key)
  • Related