public class Reachability {
class func isConnectedToNetwork() -> Bool {
var zeroAddress = sockaddr()
zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
zeroAddress.sa_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}) else { return false }
var flags = SCNetworkReachabilityFlags()
guard SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) else { return false }
return flags.contains(.reachable) && !flags.contains(.connectionRequired)
}
}
条件类型决定返回type Container<T> = T extends any[] ? ArrayContainer<T> : ObjectContainer<T>
type ArrayContainer<T> = {
set(arr: T, index: number): void
}
type ObjectContainer<T> = {
set(obj: T): void
}
const testContainer = {} as any as Container<{ boxedNumber: number } | number>
// Does not compile
testContainer.set(33)
,无法调用ObjectContainer上的任何函数。
有没有办法强制退回ObjectContainer<{ boxedNumber: number }> | ObjectContainer<number>
?
使用最新的2.8版本。
答案 0 :(得分:2)
正如@TitianCernicovaDragomir所指出的,您的问题是T
中具有裸型参数T extends XXX ? YYY : ZZZ
的条件类型最终会分布在T
中的联合上。这是as designed,但它有一个de-facto standard workaround:T
和XXX
“框”为[T] extends [XXX] ? YYY : ZZZ
中的一元组。这使得条件不依赖于裸类型参数,并且它不再破坏联合。 (T
最终处于协变位置的任何事情都应该有效...... {a: T} extends {a: XXX}
也可以。这可能会继续有效并得到支持,因为@ahejlsberg是推荐它的人,而且他是TypeScript中的main architect of conditional types。
所以在你的情况下你会做
type Container<T> = [T] extends [any[]] ? ArrayContainer<T> : ObjectContainer<T>
它会将Container<string | number>
解释为ObjectContainer<string | number>
,如你所愿。
但请注意,现在Container<string | number[]>
被解释为ObjectContainer<string | number[]>
,因为string | number[]
本身不是数组。这样可以吗?它应该是ObjectContainer<string> | ArrayContainer<number[]>
吗?还是ObjectContainer<string> & ArrayContainer<number[]>
?或者是其他东西?不确定。
希望有所帮助;祝你好运。
答案 1 :(得分:1)
问题是条件类型将遍历union中的类型并将条件应用于union中的每个项并合并结果,因此Container<{ boxedNumber: number } | number>
的结果将等同于ObjectContainer<number> | ObjectContainer<{ boxedNumber: number; }>
不是ObjectContainer<number | { boxedNumber: number; }>
。
您可以创建一个Container<{ boxedNumber: number }>
和Container的交集类型,其行为类似于您对Container<number | { boxedNumber: number }>
const testContainer = {} as any as Container<{ boxedNumber: number }> & Container<number>
testContainer.set(33)
testContainer.set({ boxedNumber: 19})
答案 2 :(得分:0)
似乎你需要额外的类型参数。
type Container<T, R> = T extends any[] ? ArrayContainer<R> : ObjectContainer<R>;
type ArrayContainer<T> = {
set(arr: T, index: number): void
}
type ObjectContainer<T> = {
set(obj: T): void
}
const testContainer = {} as Container<{}, number>;
testContainer.set(10);