我真的很難理解如何(如果可能的話)將用 Typescript 撰寫的泛型函式轉換成我可以在 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
},
]
}, [])
}
我希望能夠為 T 輸入一個結構模型并檢查輸入的值是否與鍵匹配。非常感謝這里的一些指導!
編輯:
我已經添加了如何呼叫和使用該方法。本質上,我試圖避免使用 O(n)^2 演算法,因此我試圖根據用戶的選擇構建一個過濾器串列。然后SomeType用那些內置的過濾器交叉檢查我的大部分資料 ( )。
我正在努力使用類似的原則翻譯另一個函式。
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)
}
}
這是我到目前為止。
func notInArray<Root, Value>(for keyPath: KeyPath<Root, Value>) -> (Array<Any>) -> Filter<Root, Value> {
{ values in { object in !values.contains(where: object[keyPath: keyPath]) } } }
uj5u.com熱心網友回復:
你還沒有給出你期望如何使用它,所以我需要做一些假設。我假設呼叫它的 TypeScript 如下所示:
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);
keyofSwift 中TypeScript 的等價物是KeyPath. 保持它盡可能接近 TypeScript 語法,以便更容易地看到它是如何映射的,這看起來像:
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)
為了使它更好地 Swift(而不是與 TypeScript 如此緊密地匹配),它看起來像:
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)
你的第二個例子就像第一個。
func hasInArray<Root, Values>(for keyPath: KeyPath<Root, Values>) -> (Values.Element) -> (Root) -> Bool
where Values: Sequence, Values.Element: Equatable
{
{ value in { object in object[keyPath: keyPath].contains(value) } }
}
你幾乎永遠不會想要Array<Any>。您需要一個特定元素的陣列。但在這種情況下,您根本不需要陣列;你只需要任何序列。
綜上所述,我不會這樣做。我認為如果您創建一個過濾器型別來管理它會更容易理解。
// A Filter object over a specific Target object (for example, a Person)
struct Filter<Target> {
let passes: (Target) -> Bool
}
// Filters can be created many ways
extension Filter {
// By properties equal to a value
static func keyPath<Value>(_ keyPath: KeyPath<Target, Value>, equals value: Value) -> Filter
where Value: Equatable
{
Filter { target in
target[keyPath: keyPath] == value
}
}
// By properties containing a value
static func keyPath<Seq>(_ keyPath: KeyPath<Target, Seq>, contains value: Seq.Element) -> Filter
where Seq: Sequence, Seq.Element: Equatable
{
Filter { target in
target[keyPath: keyPath].contains(value)
}
}
// By a property being a member of a sequence
static func keyPath<Seq>(_ keyPath: KeyPath<Target, Seq.Element>, isElementOf seq: Seq) -> Filter
where Seq: Sequence, Seq.Element: Equatable
{
Filter { target in
seq.contains(target[keyPath: keyPath])
}
}
// By combining other filters
static func all(of filters: [Filter]) -> Filter {
Filter { target in
filters.allSatisfy { filter in filter.passes(target) }
}
}
}
struct Person {
var name: String
var age: Int
var children: [String]
}
let filter: Filter<Person> = .all(of: [
.keyPath(\.name, equals: "Alice"),
.keyPath(\.children, contains: "Bob"),
.keyPath(\.age, isElementOf: [23, 43]),
])
let alice = Person(name: "Alice", age: 23, children: ["Bob"])
let shouldInclude = filter.passes(alice) // true
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/345360.html
